From d5194ce6cbaa4f0d79ea0546b376e39c6aed26b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Thu, 10 Jul 2025 21:04:25 +0100 Subject: [PATCH 01/62] Config entry isConnectedToNetwork --- src/common/config.cpp | 10 ++++++++++ src/common/config.h | 1 + 2 files changed, 11 insertions(+) diff --git a/src/common/config.cpp b/src/common/config.cpp index a1b12ee5d..0d73a7f5e 100644 --- a/src/common/config.cpp +++ b/src/common/config.cpp @@ -47,6 +47,7 @@ static bool isShowSplash = false; static std::string isSideTrophy = "right"; static bool compatibilityData = false; static bool checkCompatibilityOnStartup = false; +static bool isConnectedToNetwork = false; // Input static int cursorState = HideCursorState::Idle; @@ -353,6 +354,10 @@ bool getCheckCompatibilityOnStartup() { return checkCompatibilityOnStartup; } +bool getIsConnectedToNetwork() { + return isConnectedToNetwork; +} + void setGpuId(s32 selectedGpuId) { gpuId = selectedGpuId; } @@ -636,6 +641,9 @@ void load(const std::filesystem::path& path) { compatibilityData = toml::find_or(general, "compatibilityEnabled", compatibilityData); checkCompatibilityOnStartup = toml::find_or(general, "checkCompatibilityOnStartup", checkCompatibilityOnStartup); + + isConnectedToNetwork = + toml::find_or(general, "isConnectedToNetwork", isConnectedToNetwork); chooseHomeTab = toml::find_or(general, "chooseHomeTab", chooseHomeTab); entry_count += general.size(); @@ -830,6 +838,7 @@ void save(const std::filesystem::path& path) { data["General"]["sideTrophy"] = isSideTrophy; data["General"]["compatibilityEnabled"] = compatibilityData; data["General"]["checkCompatibilityOnStartup"] = checkCompatibilityOnStartup; + data["General"]["isConnectedToNetwork"] = isConnectedToNetwork; data["Input"]["cursorState"] = cursorState; data["Input"]["cursorHideTimeout"] = cursorHideTimeout; data["Input"]["useSpecialPad"] = useSpecialPad; @@ -926,6 +935,7 @@ void setDefaultValues() { isSideTrophy = "right"; compatibilityData = false; checkCompatibilityOnStartup = false; + isConnectedToNetwork = false; // Input cursorState = HideCursorState::Idle; diff --git a/src/common/config.h b/src/common/config.h index 4ace4d316..8eb17547c 100644 --- a/src/common/config.h +++ b/src/common/config.h @@ -111,6 +111,7 @@ std::filesystem::path GetSaveDataPath(); void setLoadGameSizeEnabled(bool enable); bool getCompatibilityEnabled(); bool getCheckCompatibilityOnStartup(); +bool getIsConnectedToNetwork(); std::string getUserName(); std::string getChooseHomeTab(); bool GetUseUnifiedInputConfig(); From 6f9b6b4a9c665a87ef02cf03caa00649c2c69123 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Thu, 10 Jul 2025 21:07:39 +0100 Subject: [PATCH 02/62] Stub sceKernelAddReadEvent --- src/core/libraries/kernel/equeue.cpp | 31 ++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/core/libraries/kernel/equeue.cpp b/src/core/libraries/kernel/equeue.cpp index 4d1b116c5..5b336b2d4 100644 --- a/src/core/libraries/kernel/equeue.cpp +++ b/src/core/libraries/kernel/equeue.cpp @@ -6,6 +6,8 @@ #include "common/assert.h" #include "common/debug.h" #include "common/logging/log.h" +#include "common/singleton.h" +#include "core/file_sys/fs.h" #include "core/libraries/kernel/equeue.h" #include "core/libraries/kernel/orbis_error.h" #include "core/libraries/libs.h" @@ -412,6 +414,34 @@ int PS4_SYSV_ABI sceKernelDeleteTimerEvent(SceKernelEqueue eq, int id) { : ORBIS_KERNEL_ERROR_ENOENT; } +int PS4_SYSV_ABI sceKernelAddReadEvent(SceKernelEqueue eq, int fd, size_t size, void* udata) { + if (eq == nullptr) { + return ORBIS_KERNEL_ERROR_EBADF; + } + LOG_ERROR(Kernel_Event, "(DUMMY) eq = {}, fd = {}, size = {}, udata = {:#x}", eq->GetName(), fd, size, + reinterpret_cast(udata)); + + auto* h = Common::Singleton::Instance(); + auto* file = h->GetFile(fd); + if (!file) { + return ORBIS_KERNEL_ERROR_EBADF; + } + + EqueueEvent event{}; + event.event.ident = static_cast(fd); + event.event.filter = SceKernelEvent::Filter::Read; + event.event.flags = SceKernelEvent::Flags::Add; + event.event.fflags = 0; + event.event.data = size; + event.event.udata = udata; + + if (!eq->AddEvent(event)) { + return ORBIS_KERNEL_ERROR_ENOMEM; + } + + return ORBIS_OK; +} + int PS4_SYSV_ABI sceKernelAddUserEvent(SceKernelEqueue eq, int id) { if (eq == nullptr) { return ORBIS_KERNEL_ERROR_EBADF; @@ -488,6 +518,7 @@ void RegisterEventQueue(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("jpFjmgAC5AE", "libkernel", 1, "libkernel", 1, 1, sceKernelDeleteEqueue); LIB_FUNCTION("fzyMKs9kim0", "libkernel", 1, "libkernel", 1, 1, sceKernelWaitEqueue); LIB_FUNCTION("vz+pg2zdopI", "libkernel", 1, "libkernel", 1, 1, sceKernelGetEventUserData); + LIB_FUNCTION("VHCS3rCd0PM", "libkernel", 1, "libkernel", 1, 1, sceKernelAddReadEvent); LIB_FUNCTION("4R6-OvI2cEA", "libkernel", 1, "libkernel", 1, 1, sceKernelAddUserEvent); LIB_FUNCTION("WDszmSbWuDk", "libkernel", 1, "libkernel", 1, 1, sceKernelAddUserEventEdge); LIB_FUNCTION("R74tt43xP6k", "libkernel", 1, "libkernel", 1, 1, sceKernelAddHRTimerEvent); From 6b28e457859115efe0481e40ae9b52e2076368ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Thu, 10 Jul 2025 21:14:31 +0100 Subject: [PATCH 03/62] Register some posix functions --- src/core/libraries/kernel/kernel.cpp | 2 +- src/core/libraries/kernel/threads/condvar.cpp | 2 ++ src/core/libraries/kernel/threads/pthread.cpp | 16 ++++++++++++++++ .../libraries/kernel/threads/pthread_attr.cpp | 2 ++ 4 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/core/libraries/kernel/kernel.cpp b/src/core/libraries/kernel/kernel.cpp index 3272e8727..ee6075240 100644 --- a/src/core/libraries/kernel/kernel.cpp +++ b/src/core/libraries/kernel/kernel.cpp @@ -295,7 +295,7 @@ void RegisterLib(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("lUk6wrGXyMw", "libScePosix", 1, "libkernel", 1, 1, Libraries::Net::sys_recvfrom); LIB_FUNCTION("fFxGkxF2bVo", "libScePosix", 1, "libkernel", 1, 1, Libraries::Net::sys_setsockopt); - // LIB_FUNCTION("RenI1lL1WFk", "libScePosix", 1, "libkernel", 1, 1, posix_getsockname); + LIB_FUNCTION("RenI1lL1WFk", "libScePosix", 1, "libkernel", 1, 1, posix_getsockname); LIB_FUNCTION("KuOmgKoqCdY", "libScePosix", 1, "libkernel", 1, 1, Libraries::Net::sys_bind); LIB_FUNCTION("5jRCs2axtr4", "libScePosix", 1, "libkernel", 1, 1, Libraries::Net::sceNetInetNtop); // TODO fix it to sys_ ... diff --git a/src/core/libraries/kernel/threads/condvar.cpp b/src/core/libraries/kernel/threads/condvar.cpp index 0b0545ace..0d1ef5c6a 100644 --- a/src/core/libraries/kernel/threads/condvar.cpp +++ b/src/core/libraries/kernel/threads/condvar.cpp @@ -341,6 +341,8 @@ void RegisterCond(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("mKoTx03HRWA", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_condattr_init); LIB_FUNCTION("dJcuQVn6-Iw", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_condattr_destroy); + LIB_FUNCTION("EjllaAqAPZo", "libScePosix", 1, "libkernel", 1, 1, + posix_pthread_condattr_setclock); LIB_FUNCTION("0TyVk4MSLt0", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_cond_init); LIB_FUNCTION("2MOy+rUfuhQ", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_cond_signal); LIB_FUNCTION("RXXqi4CtF8w", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_cond_destroy); diff --git a/src/core/libraries/kernel/threads/pthread.cpp b/src/core/libraries/kernel/threads/pthread.cpp index 59b427d22..e1c22bc55 100644 --- a/src/core/libraries/kernel/threads/pthread.cpp +++ b/src/core/libraries/kernel/threads/pthread.cpp @@ -324,6 +324,10 @@ PthreadT PS4_SYSV_ABI posix_pthread_self() { return g_curthread; } +void PS4_SYSV_ABI posix_pthread_set_name_np(PthreadT thread, const char* name) { + Common::SetCurrentThreadName(name); +} + void PS4_SYSV_ABI posix_pthread_yield() { std::this_thread::yield(); } @@ -332,6 +336,14 @@ void PS4_SYSV_ABI sched_yield() { std::this_thread::yield(); } +int PS4_SYSV_ABI posix_getpid() { +#ifdef WIN32 + return GetCurrentProcessId(); +#else + return getpid(); +#endif +} + int PS4_SYSV_ABI posix_pthread_once(PthreadOnce* once_control, void PS4_SYSV_ABI (*init_routine)()) { for (;;) { @@ -644,9 +656,11 @@ void RegisterThread(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("Jmi+9w9u0E4", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_create_name_np); LIB_FUNCTION("lZzFeSxPl08", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_setcancelstate); LIB_FUNCTION("a2P9wYGeZvc", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_setprio); + LIB_FUNCTION("9vyP6Z7bqzc", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_rename_np); LIB_FUNCTION("FIs3-UQT9sg", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_getschedparam); LIB_FUNCTION("Xs9hdiD7sAA", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_setschedparam); LIB_FUNCTION("6XG4B33N09g", "libScePosix", 1, "libkernel", 1, 1, sched_yield); + LIB_FUNCTION("HoLVWNanBBc", "libScePosix", 1, "libkernel", 1, 1, posix_getpid); // Posix-Kernel LIB_FUNCTION("Z4QosVuAsA0", "libkernel", 1, "libkernel", 1, 1, posix_pthread_once); @@ -669,6 +683,7 @@ void RegisterThread(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("How7B8Oet6k", "libkernel", 1, "libkernel", 1, 1, ORBIS(posix_pthread_getname_np)); LIB_FUNCTION("3kg7rT0NQIs", "libkernel", 1, "libkernel", 1, 1, posix_pthread_exit); LIB_FUNCTION("aI+OeCz8xrQ", "libkernel", 1, "libkernel", 1, 1, posix_pthread_self); + LIB_FUNCTION("oxMp8uPqa+U", "libkernel", 1, "libkernel", 1, 1, posix_pthread_set_name_np); LIB_FUNCTION("3PtV6p3QNX4", "libkernel", 1, "libkernel", 1, 1, posix_pthread_equal); LIB_FUNCTION("T72hz6ffq08", "libkernel", 1, "libkernel", 1, 1, posix_pthread_yield); LIB_FUNCTION("EI-5-jlq2dE", "libkernel", 1, "libkernel", 1, 1, posix_pthread_getthreadid_np); @@ -676,6 +691,7 @@ void RegisterThread(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("W0Hpm2X0uPE", "libkernel", 1, "libkernel", 1, 1, ORBIS(posix_pthread_setprio)); LIB_FUNCTION("rNhWz+lvOMU", "libkernel", 1, "libkernel", 1, 1, _sceKernelSetThreadDtors); LIB_FUNCTION("6XG4B33N09g", "libkernel", 1, "libkernel", 1, 1, sched_yield); + LIB_FUNCTION("HoLVWNanBBc", "libkernel", 1, "libkernel", 1, 1, posix_getpid); LIB_FUNCTION("rcrVFJsQWRY", "libkernel", 1, "libkernel", 1, 1, ORBIS(scePthreadGetaffinity)); LIB_FUNCTION("bt3CTBKmGyI", "libkernel", 1, "libkernel", 1, 1, ORBIS(scePthreadSetaffinity)); } diff --git a/src/core/libraries/kernel/threads/pthread_attr.cpp b/src/core/libraries/kernel/threads/pthread_attr.cpp index e098b00a4..26946cfb9 100644 --- a/src/core/libraries/kernel/threads/pthread_attr.cpp +++ b/src/core/libraries/kernel/threads/pthread_attr.cpp @@ -293,6 +293,8 @@ void RegisterThreadAttr(Core::Loader::SymbolsResolver* sym) { posix_pthread_attr_setstacksize); LIB_FUNCTION("RtLRV-pBTTY", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_attr_getschedpolicy); + LIB_FUNCTION("JarMIy8kKEY", "libkernel", 1, "libkernel", 1, 1, + posix_pthread_attr_setschedpolicy); LIB_FUNCTION("E+tyo3lp5Lw", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_attr_setdetachstate); LIB_FUNCTION("zHchY8ft5pk", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_attr_destroy); From 7c5978fa0537811a672dc1b3e8bc607b2186f902 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Fri, 11 Jul 2025 18:29:43 +0100 Subject: [PATCH 04/62] Stub select --- src/core/libraries/kernel/file_system.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/core/libraries/kernel/file_system.cpp b/src/core/libraries/kernel/file_system.cpp index 9dd70afc6..a2d9cc93f 100644 --- a/src/core/libraries/kernel/file_system.cpp +++ b/src/core/libraries/kernel/file_system.cpp @@ -1055,6 +1055,17 @@ s32 PS4_SYSV_ABI sceKernelUnlink(const char* path) { return result; } +s32 PS4_SYSV_ABI posix_select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, + OrbisKernelTimeval* timeout) { + LOG_ERROR(Kernel_Fs, + "(STUBBED) nfds = {}, readfds = {:#x}, writefds = {:#x}, exceptfds = {:#x}, timeout " + "= {:#x}", + nfds, reinterpret_cast(readfds), reinterpret_cast(writefds), + reinterpret_cast(exceptfds), reinterpret_cast(timeout)); + + return ORBIS_OK; +} + void RegisterFileSystem(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("6c3rCVE-fTU", "libkernel", 1, "libkernel", 1, 1, open); LIB_FUNCTION("wuCroIGjt2g", "libScePosix", 1, "libkernel", 1, 1, posix_open); @@ -1110,6 +1121,8 @@ void RegisterFileSystem(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("nKWi-N2HBV4", "libkernel", 1, "libkernel", 1, 1, sceKernelPwrite); LIB_FUNCTION("mBd4AfLP+u8", "libkernel", 1, "libkernel", 1, 1, sceKernelPwritev); LIB_FUNCTION("AUXVxWeJU-A", "libkernel", 1, "libkernel", 1, 1, sceKernelUnlink); + LIB_FUNCTION("T8fER+tIGgk", "libScePosix", 1, "libkernel", 1, 1, posix_select); + LIB_FUNCTION("T8fER+tIGgk", "libkernel", 1, "libkernel", 1, 1, posix_select); } } // namespace Libraries::Kernel From 9d9c947b9c073ed35779f38b280370cf4952e685 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Fri, 11 Jul 2025 18:33:21 +0100 Subject: [PATCH 05/62] Demote log in getsockname --- src/core/libraries/kernel/kernel.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/libraries/kernel/kernel.cpp b/src/core/libraries/kernel/kernel.cpp index ee6075240..928b6c14b 100644 --- a/src/core/libraries/kernel/kernel.cpp +++ b/src/core/libraries/kernel/kernel.cpp @@ -215,6 +215,7 @@ s32 PS4_SYSV_ABI posix_getpagesize() { s32 PS4_SYSV_ABI posix_getsockname(Libraries::Net::OrbisNetId s, Libraries::Net::OrbisNetSockaddr* addr, u32* paddrlen) { + LOG_DEBUG(Lib_Net, "s = {}", s); auto* netcall = Common::Singleton::Instance(); auto sock = netcall->FindSocket(s); if (!sock) { @@ -224,7 +225,7 @@ s32 PS4_SYSV_ABI posix_getsockname(Libraries::Net::OrbisNetId s, } s32 returncode = sock->GetSocketAddress(addr, paddrlen); if (returncode >= 0) { - LOG_ERROR(Lib_Net, "return code : {:#x}", (u32)returncode); + LOG_DEBUG(Lib_Net, "return code : {:#x}", (u32)returncode); return 0; } *Libraries::Kernel::__Error() = 0x20; From 74bddcb7d8654169092373fcfd38d4ad9d460dd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Fri, 11 Jul 2025 18:35:40 +0100 Subject: [PATCH 06/62] Stub sceKernelIsAddressSanitizerEnabled --- src/core/libraries/kernel/memory.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/core/libraries/kernel/memory.cpp b/src/core/libraries/kernel/memory.cpp index e0c359f2c..de744d0b5 100644 --- a/src/core/libraries/kernel/memory.cpp +++ b/src/core/libraries/kernel/memory.cpp @@ -318,6 +318,10 @@ s32 PS4_SYSV_ABI sceKernelIsStack(void* addr, void** start, void** end) { return memory->IsStack(std::bit_cast(addr), start, end); } +u32 PS4_SYSV_ABI sceKernelIsAddressSanitizerEnabled() { + return ORBIS_OK; +} + s32 PS4_SYSV_ABI sceKernelBatchMap(OrbisKernelBatchMapEntry* entries, s32 numEntries, s32* numEntriesOut) { return sceKernelBatchMap2(entries, numEntries, numEntriesOut, @@ -689,6 +693,7 @@ void RegisterMemory(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("BC+OG5m9+bw", "libkernel", 1, "libkernel", 1, 1, sceKernelGetDirectMemoryType); LIB_FUNCTION("pO96TwzOm5E", "libkernel", 1, "libkernel", 1, 1, sceKernelGetDirectMemorySize); LIB_FUNCTION("yDBwVAolDgg", "libkernel", 1, "libkernel", 1, 1, sceKernelIsStack); + LIB_FUNCTION("jh+8XiK4LeE", "libkernel", 1, "libkernel", 1, 1, sceKernelIsAddressSanitizerEnabled); LIB_FUNCTION("NcaWUxfMNIQ", "libkernel", 1, "libkernel", 1, 1, sceKernelMapNamedDirectMemory); LIB_FUNCTION("L-Q3LEjIbgA", "libkernel", 1, "libkernel", 1, 1, sceKernelMapDirectMemory); LIB_FUNCTION("BQQniolj9tQ", "libkernel", 1, "libkernel", 1, 1, sceKernelMapDirectMemory2); From 4aff9de22e53aeda2f63bb58a56873ee4d85f655 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Fri, 11 Jul 2025 18:36:15 +0100 Subject: [PATCH 07/62] Wire more pthread_attr functions --- src/core/libraries/kernel/threads/pthread_attr.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/core/libraries/kernel/threads/pthread_attr.cpp b/src/core/libraries/kernel/threads/pthread_attr.cpp index 26946cfb9..8c61922f4 100644 --- a/src/core/libraries/kernel/threads/pthread_attr.cpp +++ b/src/core/libraries/kernel/threads/pthread_attr.cpp @@ -289,8 +289,12 @@ int PS4_SYSV_ABI scePthreadAttrSetaffinity(PthreadAttrT* attr, const u64 mask) { void RegisterThreadAttr(Core::Loader::SymbolsResolver* sym) { // Posix LIB_FUNCTION("wtkt-teR1so", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_attr_init); + LIB_FUNCTION("vQm4fDEsWi8", "libScePosix", 1, "libkernel", 1, 1, + posix_pthread_attr_getstack); LIB_FUNCTION("2Q0z6rnBrTE", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_attr_setstacksize); + LIB_FUNCTION("Ucsu-OK+els", "libScePosix", 1, "libkernel", 1, 1, + posix_pthread_attr_get_np); LIB_FUNCTION("RtLRV-pBTTY", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_attr_getschedpolicy); LIB_FUNCTION("JarMIy8kKEY", "libkernel", 1, "libkernel", 1, 1, From 63c23dfcb7027ac80064fe3a7411744d5949efe5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Fri, 11 Jul 2025 18:46:45 +0100 Subject: [PATCH 08/62] Respect Config::isConnectedToNetwork when returning connection state --- src/core/libraries/network/net_ctl_obj.cpp | 10 ++++++++-- src/core/libraries/network/netctl.cpp | 5 ++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/core/libraries/network/net_ctl_obj.cpp b/src/core/libraries/network/net_ctl_obj.cpp index ad944cd9c..a295477b6 100644 --- a/src/core/libraries/network/net_ctl_obj.cpp +++ b/src/core/libraries/network/net_ctl_obj.cpp @@ -2,6 +2,8 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include +#include "common/config.h" +#include "common/logging/log.h" #include "core/libraries/network/net_ctl_codes.h" #include "core/libraries/network/net_ctl_obj.h" #include "core/tls.h" @@ -44,18 +46,22 @@ s32 NetCtlInternal::RegisterNpToolkitCallback(OrbisNetCtlCallbackForNpToolkit fu void NetCtlInternal::CheckCallback() { std::scoped_lock lock{m_mutex}; + const auto event = Config::getIsConnectedToNetwork() ? ORBIS_NET_CTL_EVENT_TYPE_IPOBTAINED + : ORBIS_NET_CTL_EVENT_TYPE_DISCONNECTED; for (const auto [func, arg] : callbacks) { if (func != nullptr) { - Core::ExecuteGuest(func, ORBIS_NET_CTL_EVENT_TYPE_DISCONNECTED, arg); + Core::ExecuteGuest(func, event, arg); } } } void NetCtlInternal::CheckNpToolkitCallback() { std::scoped_lock lock{m_mutex}; + const auto event = Config::getIsConnectedToNetwork() ? ORBIS_NET_CTL_EVENT_TYPE_IPOBTAINED + : ORBIS_NET_CTL_EVENT_TYPE_DISCONNECTED; for (const auto [func, arg] : nptool_callbacks) { if (func != nullptr) { - Core::ExecuteGuest(func, ORBIS_NET_CTL_EVENT_TYPE_DISCONNECTED, arg); + Core::ExecuteGuest(func, event, arg); } } } diff --git a/src/core/libraries/network/netctl.cpp b/src/core/libraries/network/netctl.cpp index 54a273dc3..e8280b89e 100644 --- a/src/core/libraries/network/netctl.cpp +++ b/src/core/libraries/network/netctl.cpp @@ -13,6 +13,7 @@ #endif #include +#include "common/config.h" #include "common/logging/log.h" #include "core/libraries/error_codes.h" #include "core/libraries/libs.h" @@ -271,7 +272,9 @@ int PS4_SYSV_ABI sceNetCtlGetScanInfoForSsidScanIpcInt() { } int PS4_SYSV_ABI sceNetCtlGetState(int* state) { - *state = ORBIS_NET_CTL_STATE_DISCONNECTED; + LOG_DEBUG(Lib_NetCtl, "connected = {}", Config::getIsConnectedToNetwork()); + const auto current_state = Config::getIsConnectedToNetwork() ? ORBIS_NET_CTL_STATE_IPOBTAINED : ORBIS_NET_CTL_STATE_DISCONNECTED; + *state = current_state; return ORBIS_OK; } From bae3dc8997726af036bf468a2e92e04032ffc3a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Fri, 11 Jul 2025 18:47:50 +0100 Subject: [PATCH 09/62] clang-format --- src/core/libraries/kernel/equeue.cpp | 4 ++-- src/core/libraries/kernel/memory.cpp | 3 ++- src/core/libraries/kernel/threads/pthread_attr.cpp | 6 ++---- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/core/libraries/kernel/equeue.cpp b/src/core/libraries/kernel/equeue.cpp index 5b336b2d4..a444b4ad6 100644 --- a/src/core/libraries/kernel/equeue.cpp +++ b/src/core/libraries/kernel/equeue.cpp @@ -418,8 +418,8 @@ int PS4_SYSV_ABI sceKernelAddReadEvent(SceKernelEqueue eq, int fd, size_t size, if (eq == nullptr) { return ORBIS_KERNEL_ERROR_EBADF; } - LOG_ERROR(Kernel_Event, "(DUMMY) eq = {}, fd = {}, size = {}, udata = {:#x}", eq->GetName(), fd, size, - reinterpret_cast(udata)); + LOG_ERROR(Kernel_Event, "(DUMMY) eq = {}, fd = {}, size = {}, udata = {:#x}", eq->GetName(), fd, + size, reinterpret_cast(udata)); auto* h = Common::Singleton::Instance(); auto* file = h->GetFile(fd); diff --git a/src/core/libraries/kernel/memory.cpp b/src/core/libraries/kernel/memory.cpp index de744d0b5..e506c29e9 100644 --- a/src/core/libraries/kernel/memory.cpp +++ b/src/core/libraries/kernel/memory.cpp @@ -693,7 +693,8 @@ void RegisterMemory(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("BC+OG5m9+bw", "libkernel", 1, "libkernel", 1, 1, sceKernelGetDirectMemoryType); LIB_FUNCTION("pO96TwzOm5E", "libkernel", 1, "libkernel", 1, 1, sceKernelGetDirectMemorySize); LIB_FUNCTION("yDBwVAolDgg", "libkernel", 1, "libkernel", 1, 1, sceKernelIsStack); - LIB_FUNCTION("jh+8XiK4LeE", "libkernel", 1, "libkernel", 1, 1, sceKernelIsAddressSanitizerEnabled); + LIB_FUNCTION("jh+8XiK4LeE", "libkernel", 1, "libkernel", 1, 1, + sceKernelIsAddressSanitizerEnabled); LIB_FUNCTION("NcaWUxfMNIQ", "libkernel", 1, "libkernel", 1, 1, sceKernelMapNamedDirectMemory); LIB_FUNCTION("L-Q3LEjIbgA", "libkernel", 1, "libkernel", 1, 1, sceKernelMapDirectMemory); LIB_FUNCTION("BQQniolj9tQ", "libkernel", 1, "libkernel", 1, 1, sceKernelMapDirectMemory2); diff --git a/src/core/libraries/kernel/threads/pthread_attr.cpp b/src/core/libraries/kernel/threads/pthread_attr.cpp index 8c61922f4..fd27fb3fe 100644 --- a/src/core/libraries/kernel/threads/pthread_attr.cpp +++ b/src/core/libraries/kernel/threads/pthread_attr.cpp @@ -289,12 +289,10 @@ int PS4_SYSV_ABI scePthreadAttrSetaffinity(PthreadAttrT* attr, const u64 mask) { void RegisterThreadAttr(Core::Loader::SymbolsResolver* sym) { // Posix LIB_FUNCTION("wtkt-teR1so", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_attr_init); - LIB_FUNCTION("vQm4fDEsWi8", "libScePosix", 1, "libkernel", 1, 1, - posix_pthread_attr_getstack); + LIB_FUNCTION("vQm4fDEsWi8", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_attr_getstack); LIB_FUNCTION("2Q0z6rnBrTE", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_attr_setstacksize); - LIB_FUNCTION("Ucsu-OK+els", "libScePosix", 1, "libkernel", 1, 1, - posix_pthread_attr_get_np); + LIB_FUNCTION("Ucsu-OK+els", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_attr_get_np); LIB_FUNCTION("RtLRV-pBTTY", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_attr_getschedpolicy); LIB_FUNCTION("JarMIy8kKEY", "libkernel", 1, "libkernel", 1, 1, From 85a96d9ab9f85f9fca4843a206d02caee054736a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Fri, 11 Jul 2025 18:51:31 +0100 Subject: [PATCH 10/62] Define NetEpoll structures --- src/core/libraries/network/net.h | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/core/libraries/network/net.h b/src/core/libraries/network/net.h index 7b6a5680c..a0a96c891 100644 --- a/src/core/libraries/network/net.h +++ b/src/core/libraries/network/net.h @@ -81,6 +81,20 @@ enum OrbisNetSocketOption : u32 { ORBIS_NET_SO_PRIORITY = 0x1203 }; +enum OrbisNetEpollFlag : u32 { + ORBIS_NET_EPOLL_CTL_ADD = 1, + ORBIS_NET_EPOLL_CTL_MOD = 2, + ORBIS_NET_EPOLL_CTL_DEL = 3, +}; + +enum OrbisNetEpollEvents : u32 { + ORBIS_NET_EPOLLIN = 0x1, + ORBIS_NET_EPOLLOUT = 0x2, + ORBIS_NET_EPOLLERR = 0x8, + ORBIS_NET_EPOLLHUP = 0x10, + ORBIS_NET_EPOLLDESCID = 0x10000, +}; + using OrbisNetId = s32; struct OrbisNetSockaddr { @@ -113,6 +127,20 @@ struct OrbisNetMsghdr { int msg_flags; }; +union OrbisNetEpollData { + void* ptr; + u32 u32; + int fd; + u64 u64; +}; + +struct OrbisNetEpollEvent { + u32 events; + u32 pad; + u64 ident; + OrbisNetEpollData data; +}; + int PS4_SYSV_ABI in6addr_any(); int PS4_SYSV_ABI in6addr_loopback(); int PS4_SYSV_ABI sce_net_dummy(); From 3fd81da9f2f63649844df74cfec6a92f18973fad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Fri, 11 Jul 2025 18:54:13 +0100 Subject: [PATCH 11/62] Set WebBrowserDialog to Initialized --- src/core/libraries/web_browser_dialog/webbrowserdialog.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/libraries/web_browser_dialog/webbrowserdialog.cpp b/src/core/libraries/web_browser_dialog/webbrowserdialog.cpp index 0b1206249..96ea8ecbe 100644 --- a/src/core/libraries/web_browser_dialog/webbrowserdialog.cpp +++ b/src/core/libraries/web_browser_dialog/webbrowserdialog.cpp @@ -4,6 +4,7 @@ #include "common/logging/log.h" #include "core/libraries/error_codes.h" #include "core/libraries/libs.h" +#include "core/libraries/system/commondialog.h" #include "core/libraries/web_browser_dialog/webbrowserdialog.h" namespace Libraries::WebBrowserDialog { @@ -25,7 +26,7 @@ s32 PS4_SYSV_ABI sceWebBrowserDialogGetResult() { s32 PS4_SYSV_ABI sceWebBrowserDialogGetStatus() { LOG_ERROR(Lib_WebBrowserDialog, "(STUBBED) called"); - return ORBIS_OK; + return (s32)Libraries::CommonDialog::Status::INITIALIZED; } s32 PS4_SYSV_ABI sceWebBrowserDialogInitialize() { From 1c73485ef9599c3e16f36cbebcdd9ea91e76b9c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Fri, 11 Jul 2025 19:05:12 +0100 Subject: [PATCH 12/62] Correctly return zero root CA certs --- src/core/libraries/network/ssl.cpp | 11 ++++++++++- src/core/libraries/network/ssl.h | 4 +++- src/core/libraries/network/ssl2.cpp | 14 ++++++++++++-- 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/core/libraries/network/ssl.cpp b/src/core/libraries/network/ssl.cpp index 1e013bc26..8d6e691d4 100644 --- a/src/core/libraries/network/ssl.cpp +++ b/src/core/libraries/network/ssl.cpp @@ -633,8 +633,17 @@ int PS4_SYSV_ABI sceSslFreeSslCertName() { return ORBIS_OK; } -int PS4_SYSV_ABI sceSslGetCaCerts() { +struct OrbisSslCaCerts { + void* certs; + u64 num; + void* pool; +}; + +int PS4_SYSV_ABI sceSslGetCaCerts(int sslCtxId, OrbisSslCaCerts* certs) { LOG_ERROR(Lib_Ssl, "(STUBBED) called"); + certs->certs = nullptr; + certs->num = 0; + certs->pool = nullptr; return ORBIS_OK; } diff --git a/src/core/libraries/network/ssl.h b/src/core/libraries/network/ssl.h index 051c6363e..f9827494a 100644 --- a/src/core/libraries/network/ssl.h +++ b/src/core/libraries/network/ssl.h @@ -11,6 +11,8 @@ class SymbolsResolver; namespace Libraries::Ssl { +struct OrbisSslCaCerts; + int PS4_SYSV_ABI CA_MGMT_allocCertDistinguishedName(); int PS4_SYSV_ABI CA_MGMT_certDistinguishedNameCompare(); int PS4_SYSV_ABI CA_MGMT_convertKeyBlobToPKCS8Key(); @@ -136,7 +138,7 @@ int PS4_SYSV_ABI sceSslEnableOptionInternal(); int PS4_SYSV_ABI sceSslFreeCaCerts(); int PS4_SYSV_ABI sceSslFreeCaList(); int PS4_SYSV_ABI sceSslFreeSslCertName(); -int PS4_SYSV_ABI sceSslGetCaCerts(); +int PS4_SYSV_ABI sceSslGetCaCerts(int sslCtxId, OrbisSslCaCerts* certs); int PS4_SYSV_ABI sceSslGetCaList(); int PS4_SYSV_ABI sceSslGetIssuerName(); int PS4_SYSV_ABI sceSslGetMemoryPoolStats(); diff --git a/src/core/libraries/network/ssl2.cpp b/src/core/libraries/network/ssl2.cpp index 701f091a3..4289a7382 100644 --- a/src/core/libraries/network/ssl2.cpp +++ b/src/core/libraries/network/ssl2.cpp @@ -128,8 +128,18 @@ int PS4_SYSV_ABI sceSslGetAlpnSelected() { return ORBIS_OK; } -int PS4_SYSV_ABI sceSslGetCaCerts() { - LOG_ERROR(Lib_Ssl2, "(STUBBED) called"); +struct OrbisSslCaCerts { + void* certs; + u64 num; + void* pool; +}; + +int PS4_SYSV_ABI sceSslGetCaCerts(int sslCtxId, OrbisSslCaCerts* certs) { + // check if it is same as libSceSsl + LOG_ERROR(Lib_Ssl2, "(DUMMY) called"); + certs->certs = nullptr; + certs->num = 0; + certs->pool = nullptr; return ORBIS_OK; } From 4baa6c4b0bc422b1e1ed10529020ae190a039ac2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Fri, 11 Jul 2025 19:08:21 +0100 Subject: [PATCH 13/62] Stub sceNetCtlGetInfoV6 --- src/core/libraries/network/netctl.cpp | 4 ++-- src/core/libraries/network/netctl.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/libraries/network/netctl.cpp b/src/core/libraries/network/netctl.cpp index e8280b89e..80850785b 100644 --- a/src/core/libraries/network/netctl.cpp +++ b/src/core/libraries/network/netctl.cpp @@ -70,8 +70,8 @@ int PS4_SYSV_ABI sceNetBweUnregisterCallbackIpcInt() { return ORBIS_OK; } -int PS4_SYSV_ABI sceNetCtlGetInfoV6() { - LOG_ERROR(Lib_NetCtl, "(STUBBED) called"); +int PS4_SYSV_ABI sceNetCtlGetInfoV6(int code, void* param) { + LOG_ERROR(Lib_NetCtl, "(STUBBED) called, code = {}", code); return ORBIS_OK; } diff --git a/src/core/libraries/network/netctl.h b/src/core/libraries/network/netctl.h index 7f139e8c3..a3efbaa59 100644 --- a/src/core/libraries/network/netctl.h +++ b/src/core/libraries/network/netctl.h @@ -79,7 +79,7 @@ int PS4_SYSV_ABI sceNetBweSetInternetConnectionTestResultIpcInt(); int PS4_SYSV_ABI sceNetBweStartInternetConnectionTestBandwidthTestIpcInt(); int PS4_SYSV_ABI sceNetBweStartInternetConnectionTestIpcInt(); int PS4_SYSV_ABI sceNetBweUnregisterCallbackIpcInt(); -int PS4_SYSV_ABI sceNetCtlGetInfoV6(); +int PS4_SYSV_ABI sceNetCtlGetInfoV6(int code, void* param); int PS4_SYSV_ABI sceNetCtlGetResultV6(); int PS4_SYSV_ABI sceNetCtlGetStateV6(); int PS4_SYSV_ABI sceNetCtlRegisterCallbackV6(); From 8590a4cdfdb03d684bc8c3f96c8d84b19d504e1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Fri, 11 Jul 2025 19:18:38 +0100 Subject: [PATCH 14/62] Handle DNS resolution through NetResolver --- src/core/libraries/network/net.cpp | 44 ++++++++++++++++++++++++++---- src/core/libraries/network/net.h | 18 ++++++++++-- 2 files changed, 53 insertions(+), 9 deletions(-) diff --git a/src/core/libraries/network/net.cpp b/src/core/libraries/network/net.cpp index 6df4f2f40..bbdf0338c 100644 --- a/src/core/libraries/network/net.cpp +++ b/src/core/libraries/network/net.cpp @@ -1388,12 +1388,12 @@ int PS4_SYSV_ABI sceNetResolverConnectDestroy() { return ORBIS_OK; } -int PS4_SYSV_ABI sceNetResolverCreate() { - LOG_ERROR(Lib_Net, "(STUBBED) called"); +int PS4_SYSV_ABI sceNetResolverCreate(const char* name, int poolid, int flags) { + LOG_ERROR(Lib_Net, "(STUBBED) called, name = {}, poolid = {}, flags = {}", name, poolid, flags); return ORBIS_OK; } -int PS4_SYSV_ABI sceNetResolverDestroy() { +int PS4_SYSV_ABI sceNetResolverDestroy(OrbisNetId resolverid) { LOG_ERROR(Lib_Net, "(STUBBED) called"); return ORBIS_OK; } @@ -1413,9 +1413,41 @@ int PS4_SYSV_ABI sceNetResolverStartAton6() { return ORBIS_OK; } -int PS4_SYSV_ABI sceNetResolverStartNtoa() { - LOG_ERROR(Lib_Net, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceNetResolverStartNtoa(OrbisNetId resolverid, const char* hostname, + OrbisNetInAddr* addr, int timeout, int retry, int flags) { + LOG_INFO(Lib_Net, + "called, resolverid = {}, hostname = {}, timeout = {}, retry = {}, flags = {}", + resolverid, hostname, timeout, retry, flags); + + if ((flags & ORBIS_NET_RESOLVER_ASYNC) != 0) { + // moves processing to EpollWait + UNREACHABLE_MSG("unimplemented"); + } + + const addrinfo hints = { + .ai_flags = AI_V4MAPPED | AI_ADDRCONFIG, + .ai_family = AF_INET, + }; + + addrinfo* info = nullptr; + auto gai_result = getaddrinfo(hostname, nullptr, &hints, &info); + + auto ret = ORBIS_OK; + if (gai_result != 0) { + // handle more errors + LOG_ERROR(Lib_Net, "address resolution for {} failed: {}", hostname, + gai_strerror(gai_result)); + *sceNetErrnoLoc() = ORBIS_NET_ERETURN; + ret = -ORBIS_NET_ERETURN | ORBIS_NET_ERROR_BASE; + } else { + ASSERT(info && info->ai_addr); + in_addr resolved_addr = ((sockaddr_in*)info->ai_addr)->sin_addr; + LOG_DEBUG(Lib_Net, "resolved address for {}: {}", hostname, inet_ntoa(resolved_addr)); + addr->s_addr = resolved_addr.s_addr; + } + + freeaddrinfo(info); + return ret; } int PS4_SYSV_ABI sceNetResolverStartNtoa6() { diff --git a/src/core/libraries/network/net.h b/src/core/libraries/network/net.h index a0a96c891..626719328 100644 --- a/src/core/libraries/network/net.h +++ b/src/core/libraries/network/net.h @@ -95,6 +95,11 @@ enum OrbisNetEpollEvents : u32 { ORBIS_NET_EPOLLDESCID = 0x10000, }; +enum OrbisNetResolverFlag : u32 { + ORBIS_NET_RESOLVER_ASYNC = 0x1, + ORBIS_NET_RESOLVER_START_NTOA_DISABLE_IPADDRESS = 0x10000, +}; + using OrbisNetId = s32; struct OrbisNetSockaddr { @@ -112,6 +117,12 @@ struct OrbisNetSockaddrIn { char sin_zero[6]; }; +using OrbisNetInAddr_t = u32; + +struct OrbisNetInAddr { + OrbisNetInAddr_t s_addr; +}; + struct OrbisNetIovec { void* iov_base; u64 iov_len; @@ -310,12 +321,13 @@ int PS4_SYSV_ABI sceNetResolverConnect(); int PS4_SYSV_ABI sceNetResolverConnectAbort(); int PS4_SYSV_ABI sceNetResolverConnectCreate(); int PS4_SYSV_ABI sceNetResolverConnectDestroy(); -int PS4_SYSV_ABI sceNetResolverCreate(); -int PS4_SYSV_ABI sceNetResolverDestroy(); +int PS4_SYSV_ABI sceNetResolverCreate(const char* name, int poolid, int flags); +int PS4_SYSV_ABI sceNetResolverDestroy(OrbisNetId resolverid); int PS4_SYSV_ABI sceNetResolverGetError(); int PS4_SYSV_ABI sceNetResolverStartAton(); int PS4_SYSV_ABI sceNetResolverStartAton6(); -int PS4_SYSV_ABI sceNetResolverStartNtoa(); +int PS4_SYSV_ABI sceNetResolverStartNtoa(OrbisNetId resolverid, const char* hostname, + OrbisNetInAddr* addr, int timeout, int retry, int flags); int PS4_SYSV_ABI sceNetResolverStartNtoa6(); int PS4_SYSV_ABI sceNetResolverStartNtoaMultipleRecords(); int PS4_SYSV_ABI sceNetResolverStartNtoaMultipleRecordsEx(); From 2aa3facd02ef5df4de17db02fb4c51197d14fc6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Fri, 11 Jul 2025 19:24:08 +0100 Subject: [PATCH 15/62] Run provided Np callback --- src/core/libraries/np_manager/np_manager.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/core/libraries/np_manager/np_manager.cpp b/src/core/libraries/np_manager/np_manager.cpp index b161a5a50..eab738e9f 100644 --- a/src/core/libraries/np_manager/np_manager.cpp +++ b/src/core/libraries/np_manager/np_manager.cpp @@ -2545,14 +2545,18 @@ struct NpStateCallbackForNpToolkit { NpStateCallbackForNpToolkit NpStateCbForNp; int PS4_SYSV_ABI sceNpCheckCallbackForLib() { - LOG_DEBUG(Lib_NpManager, "(STUBBED) called"); + LOG_DEBUG(Lib_NpManager, "called"); + + const auto state = Config::getPSNSignedIn() ? OrbisNpState::SignedIn : OrbisNpState::SignedOut; + + NpStateCbForNp.func(1, state, NpStateCbForNp.userdata); return ORBIS_OK; } int PS4_SYSV_ABI sceNpRegisterStateCallbackForToolkit(OrbisNpStateCallbackForNpToolkit callback, void* userdata) { static int id = 0; - LOG_ERROR(Lib_NpManager, "(STUBBED) called"); + LOG_WARNING(Lib_NpManager, "(DUMMY) called"); NpStateCbForNp.func = callback; NpStateCbForNp.userdata = userdata; return id; From 879d787dd0232332463b5d8f8848e8d0191449a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Fri, 11 Jul 2025 19:34:23 +0100 Subject: [PATCH 16/62] Check if returned socket is valid --- src/core/libraries/network/posix_sockets.cpp | 6 ++++++ src/core/libraries/network/sockets.h | 19 +++++++++++++++---- src/core/libraries/network/sys_net.cpp | 12 ++++++++++-- 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/core/libraries/network/posix_sockets.cpp b/src/core/libraries/network/posix_sockets.cpp index 2df375262..5a7c62bee 100644 --- a/src/core/libraries/network/posix_sockets.cpp +++ b/src/core/libraries/network/posix_sockets.cpp @@ -142,6 +142,12 @@ static void convertPosixSockaddrToOrbis(sockaddr* src, OrbisNetSockaddr* dst) { memcpy(&dst_in->sin_addr, &src_in->sin_addr, 4); } +PosixSocket::PosixSocket(int domain, int type, int protocol) : Socket(domain, type, protocol) { + sock = socket(ConvertFamilies(domain), type, protocol); + LOG_DEBUG(Lib_Net, "socket = {}", sock); + socket_type = type; +} + int PosixSocket::Close() { std::scoped_lock lock{m_mutex}; #ifdef _WIN32 diff --git a/src/core/libraries/network/sockets.h b/src/core/libraries/network/sockets.h index c54e11e66..1d5485ef3 100644 --- a/src/core/libraries/network/sockets.h +++ b/src/core/libraries/network/sockets.h @@ -51,6 +51,8 @@ struct Socket { u32* fromlen) = 0; virtual int Connect(const OrbisNetSockaddr* addr, u32 namelen) = 0; virtual int GetSocketAddress(OrbisNetSockaddr* name, u32* namelen) = 0; + virtual bool IsValid() const = 0; + virtual net_socket Native() const = 0; std::mutex m_mutex; }; @@ -65,10 +67,7 @@ struct PosixSocket : public Socket { int sockopt_ip_maxttl = 0; int sockopt_tcp_mss_to_advertise = 0; int socket_type; - explicit PosixSocket(int domain, int type, int protocol) - : Socket(domain, type, protocol), sock(socket(domain, type, protocol)) { - socket_type = type; - } + explicit PosixSocket(int domain, int type, int protocol); explicit PosixSocket(net_socket sock) : Socket(0, 0, 0), sock(sock) {} int Close() override; int SetSocketOptions(int level, int optname, const void* optval, u32 optlen) override; @@ -81,6 +80,12 @@ struct PosixSocket : public Socket { SocketPtr Accept(OrbisNetSockaddr* addr, u32* addrlen) override; int Connect(const OrbisNetSockaddr* addr, u32 namelen) override; int GetSocketAddress(OrbisNetSockaddr* name, u32* namelen) override; + bool IsValid() const override { + return sock != -1; + } + net_socket Native() const override { + return sock; + } }; struct P2PSocket : public Socket { @@ -96,6 +101,12 @@ struct P2PSocket : public Socket { SocketPtr Accept(OrbisNetSockaddr* addr, u32* addrlen) override; int Connect(const OrbisNetSockaddr* addr, u32 namelen) override; int GetSocketAddress(OrbisNetSockaddr* name, u32* namelen) override; + bool IsValid() const override { + return true; + } + net_socket Native() const override { + return {}; + } }; class NetInternal { diff --git a/src/core/libraries/network/sys_net.cpp b/src/core/libraries/network/sys_net.cpp index 087632159..bd85c1480 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 "common/error.h" #include "common/singleton.h" #include "net_error.h" #include "sockets.h" @@ -145,9 +146,16 @@ int PS4_SYSV_ABI sys_socketex(const char* name, int family, int type, int protoc switch (type) { case ORBIS_NET_SOCK_STREAM: case ORBIS_NET_SOCK_DGRAM: - case ORBIS_NET_SOCK_RAW: - sock = std::make_shared(family, type, protocol); + case ORBIS_NET_SOCK_RAW: { + const auto typed_socket = std::make_shared(family, type, protocol); + if (!typed_socket->IsValid()) { + *Libraries::Kernel::__Error() = ORBIS_NET_EPROTONOSUPPORT; + return -1; + } + + sock = std::move(typed_socket); break; + } case ORBIS_NET_SOCK_DGRAM_P2P: case ORBIS_NET_SOCK_STREAM_P2P: sock = std::make_shared(family, type, protocol); From 0627a89874c9a449a2aa1cf37d0e754c6bd688d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Fri, 11 Jul 2025 19:37:34 +0100 Subject: [PATCH 17/62] NetCtl: run provided callbacks --- src/core/libraries/network/netctl.cpp | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/core/libraries/network/netctl.cpp b/src/core/libraries/network/netctl.cpp index 80850785b..1537f705b 100644 --- a/src/core/libraries/network/netctl.cpp +++ b/src/core/libraries/network/netctl.cpp @@ -96,7 +96,9 @@ int PS4_SYSV_ABI sceNetCtlUnregisterCallbackV6() { } int PS4_SYSV_ABI sceNetCtlCheckCallback() { - LOG_DEBUG(Lib_NetCtl, "(STUBBED) called"); + LOG_DEBUG(Lib_NetCtl, "called"); + + netctl.CheckCallback(); return ORBIS_OK; } @@ -299,7 +301,7 @@ int PS4_SYSV_ABI sceNetCtlGetWifiType() { } int PS4_SYSV_ABI sceNetCtlInit() { - LOG_ERROR(Lib_NetCtl, "(STUBBED) called"); + LOG_DEBUG(Lib_NetCtl, "called"); return ORBIS_OK; } @@ -312,12 +314,17 @@ int PS4_SYSV_ABI sceNetCtlRegisterCallback(OrbisNetCtlCallback func, void* arg, if (!func || !cid) { return ORBIS_NET_CTL_ERROR_INVALID_ADDR; } + s32 result = netctl.RegisterCallback(func, arg); + if (result < 0) { + LOG_DEBUG(Lib_NetCtl, "failed with {:#x}", result); return result; } else { + LOG_DEBUG(Lib_NetCtl, "*cid = {}", result); *cid = result; } + return ORBIS_OK; } @@ -387,7 +394,9 @@ int PS4_SYSV_ABI Func_D8DCB6973537A3DC() { } int PS4_SYSV_ABI sceNetCtlCheckCallbackForNpToolkit() { - LOG_DEBUG(Lib_NetCtl, "(STUBBED) called"); + LOG_DEBUG(Lib_NetCtl, "called"); + + netctl.CheckNpToolkitCallback(); return ORBIS_OK; } @@ -401,10 +410,14 @@ int PS4_SYSV_ABI sceNetCtlRegisterCallbackForNpToolkit(OrbisNetCtlCallbackForNpT if (!func || !cid) { return ORBIS_NET_CTL_ERROR_INVALID_ADDR; } + s32 result = netctl.RegisterNpToolkitCallback(func, arg); + if (result < 0) { + LOG_WARNING(Lib_NetCtl, "failed with {:#x}", result); return result; } else { + LOG_DEBUG(Lib_NetCtl, "*cid = {}", result); *cid = result; } return ORBIS_OK; From 43ca1ede01b85142e5b50e602ec844a65aa60c16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Fri, 11 Jul 2025 19:42:45 +0100 Subject: [PATCH 18/62] sys_net increase logging --- src/core/libraries/network/sys_net.cpp | 29 ++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/src/core/libraries/network/sys_net.cpp b/src/core/libraries/network/sys_net.cpp index bd85c1480..012f8b59b 100644 --- a/src/core/libraries/network/sys_net.cpp +++ b/src/core/libraries/network/sys_net.cpp @@ -13,6 +13,8 @@ namespace Libraries::Net { int PS4_SYSV_ABI sys_connect(OrbisNetId s, const OrbisNetSockaddr* addr, u32 addrlen) { + LOG_WARNING(Lib_Net, "s = {}", s); + auto* netcall = Common::Singleton::Instance(); auto sock = netcall->FindSocket(s); if (!sock) { @@ -29,6 +31,9 @@ int PS4_SYSV_ABI sys_connect(OrbisNetId s, const OrbisNetSockaddr* addr, u32 add return -1; } int PS4_SYSV_ABI sys_bind(OrbisNetId s, const OrbisNetSockaddr* addr, u32 addrlen) { + LOG_DEBUG(Lib_Net, "s = {}, addr = {:#x}, addrlen = {}", s, reinterpret_cast(addr), + addrlen); + auto* netcall = Common::Singleton::Instance(); auto sock = netcall->FindSocket(s); if (!sock) { @@ -45,6 +50,8 @@ int PS4_SYSV_ABI sys_bind(OrbisNetId s, const OrbisNetSockaddr* addr, u32 addrle return -1; } int PS4_SYSV_ABI sys_accept(OrbisNetId s, OrbisNetSockaddr* addr, u32* paddrlen) { + LOG_WARNING(Lib_Net, "(DUMMY) called"); + auto* netcall = Common::Singleton::Instance(); auto sock = netcall->FindSocket(s); if (!sock) { @@ -55,7 +62,8 @@ int PS4_SYSV_ABI sys_accept(OrbisNetId s, OrbisNetSockaddr* addr, u32* paddrlen) auto new_sock = sock->Accept(addr, paddrlen); if (!new_sock) { *Libraries::Kernel::__Error() = ORBIS_NET_EBADF; - LOG_ERROR(Lib_Net, "error creating new socket for accepting"); + LOG_ERROR(Lib_Net, "error creating new socket for accepting: {}", + Common::GetLastErrorMsg()); return -1; } auto id = ++netcall->next_sock_id; @@ -67,6 +75,8 @@ int PS4_SYSV_ABI sys_getpeername(OrbisNetId s, const OrbisNetSockaddr* addr, u32 return -1; } int PS4_SYSV_ABI sys_getsockname(OrbisNetId s, OrbisNetSockaddr* addr, u32* paddrlen) { + LOG_WARNING(Lib_Net, "(DUMMY) called"); + auto* netcall = Common::Singleton::Instance(); auto sock = netcall->FindSocket(s); if (!sock) { @@ -83,6 +93,8 @@ int PS4_SYSV_ABI sys_getsockname(OrbisNetId s, OrbisNetSockaddr* addr, u32* padd return -1; } int PS4_SYSV_ABI sys_getsockopt(OrbisNetId s, int level, int optname, void* optval, u32* optlen) { + LOG_WARNING(Lib_Net, "(DUMMY) called"); + auto* netcall = Common::Singleton::Instance(); auto sock = netcall->FindSocket(s); if (!sock) { @@ -99,6 +111,8 @@ int PS4_SYSV_ABI sys_getsockopt(OrbisNetId s, int level, int optname, void* optv return -1; } int PS4_SYSV_ABI sys_listen(OrbisNetId s, int backlog) { + LOG_DEBUG(Lib_Net, "s = {}, backlog = {}", s, backlog); + auto* netcall = Common::Singleton::Instance(); auto sock = netcall->FindSocket(s); if (!sock) { @@ -114,8 +128,11 @@ int PS4_SYSV_ABI sys_listen(OrbisNetId s, int backlog) { LOG_ERROR(Lib_Net, "error code returned : {:#x}", (u32)returncode); return -1; } + int PS4_SYSV_ABI sys_setsockopt(OrbisNetId s, int level, int optname, const void* optval, u32 optlen) { + LOG_WARNING(Lib_Net, "netId = {}", s); + auto* netcall = Common::Singleton::Instance(); auto sock = netcall->FindSocket(s); if (!sock) { @@ -124,6 +141,7 @@ int PS4_SYSV_ABI sys_setsockopt(OrbisNetId s, int level, int optname, const void return -1; } int returncode = sock->SetSocketOptions(level, optname, optval, optlen); + LOG_INFO(Lib_Net, "returncode = {}", returncode); if (returncode >= 0) { return returncode; } @@ -176,6 +194,8 @@ int PS4_SYSV_ABI sys_netabort(OrbisNetId s, int flags) { return -1; } int PS4_SYSV_ABI sys_socketclose(OrbisNetId s) { + LOG_WARNING(Lib_Net, "(DUMMY) called"); + auto* netcall = Common::Singleton::Instance(); auto sock = netcall->FindSocket(s); if (!sock) { @@ -193,6 +213,8 @@ int PS4_SYSV_ABI sys_socketclose(OrbisNetId s) { } int PS4_SYSV_ABI sys_sendto(OrbisNetId s, const void* buf, u64 len, int flags, const OrbisNetSockaddr* addr, u32 addrlen) { + LOG_WARNING(Lib_Net, "s = {}, len = {}, flags = {:#x}, addrlen = {}", s, len, flags, addrlen); + auto* netcall = Common::Singleton::Instance(); auto sock = netcall->FindSocket(s); if (!sock) { @@ -214,6 +236,9 @@ int PS4_SYSV_ABI sys_sendmsg(OrbisNetId s, const OrbisNetMsghdr* msg, int flags) } int PS4_SYSV_ABI sys_recvfrom(OrbisNetId s, void* buf, u64 len, int flags, OrbisNetSockaddr* addr, u32* paddrlen) { + // LOG_INFO(Lib_Net, "s = {}, buf = {:#x}, len = {}, flags = {:#x}", s, + // reinterpret_cast(buf), len, flags); + auto* netcall = Common::Singleton::Instance(); auto sock = netcall->FindSocket(s); if (!sock) { @@ -226,7 +251,7 @@ int PS4_SYSV_ABI sys_recvfrom(OrbisNetId s, void* buf, u64 len, int flags, Orbis return returncode; } *Libraries::Kernel::__Error() = returncode; - LOG_ERROR(Lib_Net, "error code returned : {:#x}", (u32)returncode); + // LOG_ERROR(Lib_Net, "error code returned : {:#x}", (u32)returncode); return -1; } int PS4_SYSV_ABI sys_recvmsg(OrbisNetId s, OrbisNetMsghdr* msg, int flags) { From b11f9af64a9dbef95174aea1bdf4ab9558677b74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Fri, 11 Jul 2025 19:44:15 +0100 Subject: [PATCH 19/62] NetEpoll wip --- src/core/libraries/network/net.cpp | 273 +++++++++++++++++++++++++++-- src/core/libraries/network/net.h | 10 +- 2 files changed, 266 insertions(+), 17 deletions(-) diff --git a/src/core/libraries/network/net.cpp b/src/core/libraries/network/net.cpp index bbdf0338c..22fec11e9 100644 --- a/src/core/libraries/network/net.cpp +++ b/src/core/libraries/network/net.cpp @@ -11,7 +11,9 @@ #endif #include +#include #include "common/assert.h" +#include "common/error.h" #include "common/logging/log.h" #include "common/singleton.h" #include "core/libraries/error_codes.h" @@ -20,10 +22,42 @@ #include "net_error.h" #include "net_util.h" #include "netctl.h" +#include "sockets.h" #include "sys_net.h" +#ifdef __linux__ +#include +#endif namespace Libraries::Net { +struct Epoll { + std::vector> events{}; + const char* name; + int epoll_fd; + + explicit Epoll(const char* name_) : name(name_), epoll_fd(epoll_create1(0)) { + ASSERT(epoll_fd != -1); + } + + bool Destroyed() const noexcept { + return destroyed; + } + + void Destroy() noexcept { + events.clear(); + close(epoll_fd); + epoll_fd = -1; + name = nullptr; + destroyed = true; + } + +private: + bool destroyed{}; +}; + +std::vector epolls; +std::mutex epolls_mutex; + static thread_local int32_t net_errno = 0; static bool g_isNetInitialized = true; // TODO init it properly @@ -72,6 +106,8 @@ OrbisNetId PS4_SYSV_ABI sceNetAccept(OrbisNetId s, OrbisNetSockaddr* addr, u32* if (!g_isNetInitialized) { return ORBIS_NET_ERROR_ENOTINIT; } + LOG_WARNING(Lib_Net, "(DUMMY) called"); + int result; int err; int positiveErr; @@ -169,6 +205,8 @@ int PS4_SYSV_ABI sceNetBind(OrbisNetId s, const OrbisNetSockaddr* addr, u32 addr if (!g_isNetInitialized) { return ORBIS_NET_ERROR_ENOTINIT; } + LOG_INFO(Lib_Net, "called, s = {}", s); + int result; int err; int positiveErr; @@ -551,6 +589,8 @@ int PS4_SYSV_ABI sceNetConnect(OrbisNetId s, const OrbisNetSockaddr* addr, u32 a if (!g_isNetInitialized) { return ORBIS_NET_ERROR_ENOTINIT; } + LOG_WARNING(Lib_Net, "s = {}", s); + int result; int err; int positiveErr; @@ -664,28 +704,190 @@ int PS4_SYSV_ABI sceNetEpollAbort() { return ORBIS_OK; } -int PS4_SYSV_ABI sceNetEpollControl() { - LOG_ERROR(Lib_Net, "(STUBBED) called"); +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 PS4_SYSV_ABI sceNetEpollControl(OrbisNetId epollid, OrbisNetEpollFlag op, OrbisNetId id, + OrbisNetEpollEvent* event) { + LOG_WARNING(Lib_Net, "called, epollid = {}, op = {}, id = {}", epollid, + magic_enum::enum_name(op), id); + + std::scoped_lock lock{epolls_mutex}; + if (epollid >= epolls.size() || epolls[epollid].Destroyed()) { + return -ORBIS_NET_EBADF; + } + + auto find_id = [&](OrbisNetId id) { + return std::ranges::find_if(epolls[epollid].events, + [&](const auto& el) { return el.first == id; }); + }; + + switch (op) { + case ORBIS_NET_EPOLL_CTL_ADD: { + if (event == nullptr) { + return -ORBIS_NET_EINVAL; + } + if (find_id(id) != epolls[epollid].events.end()) { + return -ORBIS_NET_EEXIST; + } + +#ifdef __linux__ + const auto socket = Common::Singleton::Instance()->socks[id]; + epoll_event native_event = {.events = ConvertEpollEventsIn(event->events), + .data = {.fd = id}}; + ASSERT(epoll_ctl(epolls[epollid].epoll_fd, EPOLL_CTL_ADD, socket->Native(), + &native_event) == 0); +#endif + epolls[epollid].events.emplace_back(id, *event); + break; + } + case ORBIS_NET_EPOLL_CTL_MOD: { + if (event == nullptr) { + return -ORBIS_NET_EINVAL; + } + + auto it = find_id(id); + if (it == epolls[epollid].events.end()) { + return -ORBIS_NET_EEXIST; + } + + it->second = *event; + UNREACHABLE(); + break; + } + case ORBIS_NET_EPOLL_CTL_DEL: { + if (event != nullptr) { + return -ORBIS_NET_EINVAL; + } + + auto it = find_id(id); + if (it == epolls[epollid].events.end()) { + return -ORBIS_NET_EBADF; + } + +#ifdef __linux__ + const auto socket = Common::Singleton::Instance()->socks[id]; + ASSERT(epoll_ctl(epolls[epollid].epoll_fd, EPOLL_CTL_DEL, socket->Native(), nullptr) == 0); +#endif + epolls[epollid].events.erase(it); + break; + } + default: + return -ORBIS_NET_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_WARNING(Lib_Net, "called, name = {}, flags = {}", name, flags); + if (flags != 0) { + return -ORBIS_NET_EINVAL; + } + + std::scoped_lock lock{epolls_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; + } +} + +int PS4_SYSV_ABI sceNetEpollDestroy(OrbisNetId epollid) { + LOG_INFO(Lib_Net, "called, epollid = {}", epollid); + + std::scoped_lock lock{epolls_mutex}; + if (epollid >= epolls.size() || epolls[epollid].Destroyed()) { + return -ORBIS_NET_EBADF; + } + + epolls[epollid].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) { + LOG_WARNING(Lib_Net, "called, epollid = {}, maxevents = {}, timeout = {}", epollid, maxevents, + timeout); -int PS4_SYSV_ABI sceNetEpollWait() { - LOG_TRACE(Lib_Net, "(STUBBED) called"); + std::scoped_lock lock{epolls_mutex}; + if (epollid >= epolls.size() || epolls[epollid].Destroyed()) { + return -ORBIS_NET_EBADF; + } +#ifdef __linux__ + std::vector native_events{static_cast(maxevents)}; + int result = epoll_wait(epolls[epollid].epoll_fd, native_events.data(), maxevents, + timeout == -1 ? timeout : timeout / 1000); + if (result < 0) { + LOG_ERROR(Lib_Net, "epoll_wait failed with {}", Common::GetLastErrorMsg()); + return 0; + } else if (result == 0) { + LOG_DEBUG(Lib_Net, "timed out"); + return 0; + } else { + for (int i = 0; i < result; ++i) { + const auto& current_event = native_events[i]; + LOG_INFO(Lib_Net, "native_event[{}] = ( .events = {}, .data = {:#x} )", i, + current_event.events, current_event.data.u64); + const auto it = std::ranges::find_if(epolls[epollid].events, [&](auto& el) { + return el.first == current_event.data.fd; + }); + ASSERT(it != epolls[epollid].events.end()); + events[i] = { + .events = ConvertEpollEventsOut(current_event.events), + .ident = static_cast(current_event.data.fd), + .data = it->second.data, + }; + LOG_INFO(Lib_Net, "event[{}] = ( .events = {:#x}, .ident = {}, .data = {:#x} )", i, + events[i].events, events[i].ident, events[i].data.u64); + } + return result; + } +#else + UNREACHABLE_MSG("sadness"); +#endif return ORBIS_OK; } int* PS4_SYSV_ABI sceNetErrnoLoc() { - LOG_ERROR(Lib_Net, "(STUBBED) called"); + LOG_TRACE(Lib_Net, "called"); return &net_errno; } @@ -764,6 +966,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); @@ -785,6 +989,8 @@ int PS4_SYSV_ABI sceNetGetpeername(OrbisNetId s, OrbisNetSockaddr* addr, u32* pa if (!g_isNetInitialized) { return ORBIS_NET_ERROR_ENOTINIT; } + LOG_WARNING(Lib_Net, "(DUMMY) called"); + int result; int err; int positiveErr; @@ -847,6 +1053,8 @@ int PS4_SYSV_ABI sceNetGetsockname(OrbisNetId s, OrbisNetSockaddr* addr, u32* pa if (!g_isNetInitialized) { return ORBIS_NET_ERROR_ENOTINIT; } + LOG_INFO(Lib_Net, "called, s = {}", s); + int result; int err; int positiveErr; @@ -1079,6 +1287,8 @@ const char* PS4_SYSV_ABI sceNetInetNtop(int af, const void* src, char* dst, u32 LOG_ERROR(Lib_Net, "returned ORBIS_NET_ENOSPC"); return nullptr; } + LOG_DEBUG(Lib_Net, "called, af = {}"); + const char* returnvalue = nullptr; switch (af) { case ORBIS_NET_AF_INET: @@ -1095,6 +1305,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, "returned {}", dst); } return returnvalue; } @@ -1104,14 +1316,25 @@ int PS4_SYSV_ABI sceNetInetNtopWithScopeId() { return ORBIS_OK; } +static int ConvertFamilies(int family) { + switch (family) { + case ORBIS_NET_AF_INET: + return AF_INET; + case ORBIS_NET_AF_INET6: + return AF_INET6; + default: + UNREACHABLE_MSG("unsupported socket family {}", family); + } +} + int PS4_SYSV_ABI sceNetInetPton(int af, const char* src, void* dst) { #ifdef WIN32 int res = InetPtonA(af, src, dst); #else - int res = inet_pton(af, src, dst); + int res = inet_pton(ConvertFamilies(af), src, dst); #endif if (res < 0) { - UNREACHABLE(); + UNREACHABLE_MSG("af = {}, src = {}, dst = {:#x}", af, src, reinterpret_cast(dst)); } return res; } @@ -1155,6 +1378,8 @@ int PS4_SYSV_ABI sceNetListen(OrbisNetId s, int backlog) { if (!g_isNetInitialized) { return ORBIS_NET_ERROR_ENOTINIT; } + LOG_WARNING(Lib_Net, "(DUMMY) called"); + int result; int err; int positiveErr; @@ -1240,6 +1465,8 @@ int PS4_SYSV_ABI sceNetRecv(OrbisNetId s, void* buf, u64 len, int flags) { if (!g_isNetInitialized) { return ORBIS_NET_ERROR_ENOTINIT; } + LOG_WARNING(Lib_Net, "called, s = {}, len = {}, flags = {}", s, len, flags); + int result; int err; int positiveErr; @@ -1283,6 +1510,8 @@ int PS4_SYSV_ABI sceNetRecvfrom(OrbisNetId s, void* buf, u64 len, int flags, Orb if (!g_isNetInitialized) { return ORBIS_NET_ERROR_ENOTINIT; } + // LOG_INFO(Lib_Net, "called, s = {}, len = {}, flags = {}", s, len, flags); + int result; int err; int positiveErr; @@ -1325,6 +1554,8 @@ int PS4_SYSV_ABI sceNetRecvmsg(OrbisNetId s, OrbisNetMsghdr* msg, int flags) { if (!g_isNetInitialized) { return ORBIS_NET_ERROR_ENOTINIT; } + LOG_WARNING(Lib_Net, "(DUMMY) called"); + int result; int err; int positiveErr; @@ -1469,6 +1700,8 @@ int PS4_SYSV_ABI sceNetSend(OrbisNetId s, const void* buf, u64 len, int flags) { if (!g_isNetInitialized) { return ORBIS_NET_ERROR_ENOTINIT; } + LOG_WARNING(Lib_Net, "called, s = {}, len = {}, flags = {}", s, len, flags); + int result; int err; int positiveErr; @@ -1511,6 +1744,8 @@ int PS4_SYSV_ABI sceNetSendmsg(OrbisNetId s, const OrbisNetMsghdr* msg, int flag if (!g_isNetInitialized) { return ORBIS_NET_ERROR_ENOTINIT; } + LOG_WARNING(Lib_Net, "(DUMMY) called"); + int result; int err; int positiveErr; @@ -1554,6 +1789,8 @@ int PS4_SYSV_ABI sceNetSendto(OrbisNetId s, const void* buf, u64 len, int flags, if (!g_isNetInitialized) { return ORBIS_NET_ERROR_ENOTINIT; } + LOG_WARNING(Lib_Net, "(DUMMY) called"); + int result; int err; int positiveErr; @@ -1740,6 +1977,8 @@ int PS4_SYSV_ABI sceNetShutdown(OrbisNetId s, int how) { if (!g_isNetInitialized) { return ORBIS_NET_ERROR_ENOTINIT; } + LOG_WARNING(Lib_Net, "(DUMMY) called"); + int result; int err; int positiveErr; @@ -1782,6 +2021,9 @@ OrbisNetId PS4_SYSV_ABI sceNetSocket(const char* name, int family, int type, int if (!g_isNetInitialized) { return ORBIS_NET_ERROR_ENOTINIT; } + LOG_INFO(Lib_Net, "name = {}, family = {}, type = {}, protocol = {}", name ? name : "no-named", + family, type, protocol); + int result; int err; int positiveErr; @@ -1790,6 +2032,7 @@ OrbisNetId PS4_SYSV_ABI sceNetSocket(const char* name, int family, int type, int result = sys_socketex(name, family, type, protocol); if (result >= 0) { + LOG_INFO(Lib_Net, "netId = {}", result); return result; // Success } @@ -1824,6 +2067,8 @@ int PS4_SYSV_ABI sceNetSocketAbort(OrbisNetId s, int flags) { if (!g_isNetInitialized) { return ORBIS_NET_ERROR_ENOTINIT; } + LOG_WARNING(Lib_Net, "(DUMMY) called"); + int result; int err; int positiveErr; @@ -1866,6 +2111,8 @@ int PS4_SYSV_ABI sceNetSocketClose(OrbisNetId s) { if (!g_isNetInitialized) { return ORBIS_NET_ERROR_ENOTINIT; } + LOG_INFO(Lib_Net, "netId = {}", s); + int result; int err; int positiveErr; diff --git a/src/core/libraries/network/net.h b/src/core/libraries/network/net.h index 626719328..2b7d42cfe 100644 --- a/src/core/libraries/network/net.h +++ b/src/core/libraries/network/net.h @@ -257,10 +257,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(); From 166fad2aa890f6ca6b3464948546b8d73e6bbfa9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Fri, 11 Jul 2025 19:57:42 +0100 Subject: [PATCH 20/62] Return connection status in NetCtlGetInfo --- src/core/libraries/network/netctl.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/core/libraries/network/netctl.cpp b/src/core/libraries/network/netctl.cpp index 1537f705b..463b81e7b 100644 --- a/src/core/libraries/network/netctl.cpp +++ b/src/core/libraries/network/netctl.cpp @@ -163,6 +163,8 @@ int PS4_SYSV_ABI sceNetCtlGetIfStat() { } int PS4_SYSV_ABI sceNetCtlGetInfo(int code, OrbisNetCtlInfo* info) { + LOG_DEBUG(Lib_NetCtl, "code = {}", code); + switch (code) { case ORBIS_NET_CTL_INFO_DEVICE: info->device = ORBIS_NET_CTL_DEVICE_WIRED; @@ -176,7 +178,8 @@ int PS4_SYSV_ABI sceNetCtlGetInfo(int code, OrbisNetCtlInfo* info) { info->mtu = 1500; // default value break; case ORBIS_NET_CTL_INFO_LINK: - info->link = ORBIS_NET_CTL_LINK_DISCONNECTED; + info->link = Config::getIsConnectedToNetwork() ? ORBIS_NET_CTL_LINK_CONNECTED + : ORBIS_NET_CTL_LINK_DISCONNECTED; break; case ORBIS_NET_CTL_INFO_IP_ADDRESS: { strcpy(info->ip_address, From a810dbe31da6f20ae16320729cf9d5ed27631db1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Fri, 11 Jul 2025 20:01:06 +0100 Subject: [PATCH 21/62] Return more hardcoded connection info --- src/core/libraries/network/netctl.cpp | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/core/libraries/network/netctl.cpp b/src/core/libraries/network/netctl.cpp index 463b81e7b..32cab7c74 100644 --- a/src/core/libraries/network/netctl.cpp +++ b/src/core/libraries/network/netctl.cpp @@ -199,11 +199,30 @@ int PS4_SYSV_ABI sceNetCtlGetInfo(int code, OrbisNetCtlInfo* info) { } break; } - + case ORBIS_NET_CTL_INFO_PRIMARY_DNS: + strcpy(info->primary_dns, "1.1.1.1"); + break; + case ORBIS_NET_CTL_INFO_SECONDARY_DNS: + strcpy(info->secondary_dns, "1.1.1.1"); + break; + case ORBIS_NET_CTL_INFO_HTTP_PROXY_CONFIG: + info->http_proxy_config = 0; + break; + case ORBIS_NET_CTL_INFO_HTTP_PROXY_SERVER: + strcpy(info->http_proxy_server, "0.0.0.0"); + break; + case ORBIS_NET_CTL_INFO_HTTP_PROXY_PORT: + info->http_proxy_port = 0; + break; + case ORBIS_NET_CTL_INFO_IP_CONFIG: + info->ip_config = 1; // static + break; + case ORBIS_NET_CTL_INFO_DHCP_HOSTNAME: + // info-> = ; + break; default: LOG_ERROR(Lib_NetCtl, "{} unsupported code", code); } - LOG_DEBUG(Lib_NetCtl, "(STUBBED) called"); return ORBIS_OK; } @@ -278,7 +297,8 @@ int PS4_SYSV_ABI sceNetCtlGetScanInfoForSsidScanIpcInt() { int PS4_SYSV_ABI sceNetCtlGetState(int* state) { LOG_DEBUG(Lib_NetCtl, "connected = {}", Config::getIsConnectedToNetwork()); - const auto current_state = Config::getIsConnectedToNetwork() ? ORBIS_NET_CTL_STATE_IPOBTAINED : ORBIS_NET_CTL_STATE_DISCONNECTED; + const auto current_state = Config::getIsConnectedToNetwork() ? ORBIS_NET_CTL_STATE_IPOBTAINED + : ORBIS_NET_CTL_STATE_DISCONNECTED; *state = current_state; return ORBIS_OK; } From 78e4a860888980258141b40b2311970c83752a66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Fri, 11 Jul 2025 20:03:01 +0100 Subject: [PATCH 22/62] Increase logging in posix sockets --- src/core/libraries/network/posix_sockets.cpp | 53 +++++++++++++++++--- 1 file changed, 46 insertions(+), 7 deletions(-) diff --git a/src/core/libraries/network/posix_sockets.cpp b/src/core/libraries/network/posix_sockets.cpp index 5a7c62bee..1266ca86b 100644 --- a/src/core/libraries/network/posix_sockets.cpp +++ b/src/core/libraries/network/posix_sockets.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include +#include "common/error.h" #include "net.h" #include "net_error.h" #include "sockets.h" @@ -108,6 +109,17 @@ static int ConvertReturnErrorCode(int retval) { return retval; } +static int ConvertFamilies(int family) { + switch (family) { + case ORBIS_NET_AF_INET: + return AF_INET; + case ORBIS_NET_AF_INET6: + return AF_INET6; + default: + UNREACHABLE_MSG("unsupported socket family {}", family); + } +} + static int ConvertLevels(int level) { switch (level) { case ORBIS_NET_SOL_SOCKET: @@ -116,8 +128,9 @@ static int ConvertLevels(int level) { return IPPROTO_IP; case ORBIS_NET_IPPROTO_TCP: return IPPROTO_TCP; + default: + UNREACHABLE_MSG("{}", level); } - return -1; } static void convertOrbisNetSockaddrToPosix(const OrbisNetSockaddr* src, sockaddr* dst) { @@ -160,19 +173,27 @@ int PosixSocket::Close() { int PosixSocket::Bind(const OrbisNetSockaddr* addr, u32 addrlen) { std::scoped_lock lock{m_mutex}; + sockaddr addr2; convertOrbisNetSockaddrToPosix(addr, &addr2); - return ConvertReturnErrorCode(::bind(sock, &addr2, sizeof(sockaddr_in))); + const auto result = ::bind(sock, &addr2, sizeof(addr2)); + LOG_DEBUG(Lib_Net, "raw bind result = {}, errno = {}", result, + result == -1 ? Common::GetLastErrorMsg() : "none"); + return ConvertReturnErrorCode(result); } int PosixSocket::Listen(int backlog) { std::scoped_lock lock{m_mutex}; + LOG_DEBUG(Lib_Net, "called"); + return ConvertReturnErrorCode(::listen(sock, backlog)); } int PosixSocket::SendPacket(const void* msg, u32 len, int flags, const OrbisNetSockaddr* to, u32 tolen) { std::scoped_lock lock{m_mutex}; + LOG_DEBUG(Lib_Net, "called"); + if (to != nullptr) { sockaddr addr; convertOrbisNetSockaddrToPosix(to, &addr); @@ -186,6 +207,8 @@ int PosixSocket::SendPacket(const void* msg, u32 len, int flags, const OrbisNetS int PosixSocket::ReceivePacket(void* buf, u32 len, int flags, OrbisNetSockaddr* from, u32* fromlen) { std::scoped_lock lock{m_mutex}; + // LOG_DEBUG(Lib_Net, "len = {}, flags = {:#x}, from = {:#x}", len, flags, + // reinterpret_cast(from)); if (from != nullptr) { sockaddr addr; int res = recvfrom(sock, (char*)buf, len, flags, &addr, (socklen_t*)fromlen); @@ -199,15 +222,20 @@ int PosixSocket::ReceivePacket(void* buf, u32 len, int flags, OrbisNetSockaddr* SocketPtr PosixSocket::Accept(OrbisNetSockaddr* addr, u32* addrlen) { std::scoped_lock lock{m_mutex}; + LOG_DEBUG(Lib_Net, "called"); + sockaddr addr2; - net_socket new_socket = ::accept(sock, &addr2, (socklen_t*)addrlen); + socklen_t len = sizeof(addr2); + net_socket new_socket = ::accept(sock, &addr2, &len); #ifdef _WIN32 if (new_socket != INVALID_SOCKET) { #else if (new_socket >= 0) { #endif - convertPosixSockaddrToOrbis(&addr2, addr); - *addrlen = sizeof(OrbisNetSockaddrIn); + if (addr && addrlen) { + convertPosixSockaddrToOrbis(&addr2, addr); + *addrlen = sizeof(OrbisNetSockaddrIn); + } return std::make_shared(new_socket); } return nullptr; @@ -215,13 +243,23 @@ SocketPtr PosixSocket::Accept(OrbisNetSockaddr* addr, u32* addrlen) { int PosixSocket::Connect(const OrbisNetSockaddr* addr, u32 namelen) { std::scoped_lock lock{m_mutex}; + LOG_DEBUG(Lib_Net, "called"); + sockaddr addr2; convertOrbisNetSockaddrToPosix(addr, &addr2); - return ::connect(sock, &addr2, sizeof(sockaddr_in)); + 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)); + return ConvertReturnErrorCode(result); } int PosixSocket::GetSocketAddress(OrbisNetSockaddr* name, u32* namelen) { std::scoped_lock lock{m_mutex}; + LOG_DEBUG(Lib_Net, "called"); + sockaddr addr; convertOrbisNetSockaddrToPosix(name, &addr); if (name != nullptr) { @@ -248,8 +286,9 @@ int PosixSocket::GetSocketAddress(OrbisNetSockaddr* name, u32* namelen) { return 0 int PosixSocket::SetSocketOptions(int level, int optname, const void* optval, u32 optlen) { - std::scoped_lock lock{m_mutex}; level = ConvertLevels(level); + LOG_INFO(Lib_Net, "level = {}, optname = {}, optlen = {}", level, optname, optlen); + std::scoped_lock lock{m_mutex}; ::linger native_linger; if (level == SOL_SOCKET) { switch (optname) { From f40ea8851c1f2019ce68dd6bbca32e8827f0c7e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Sat, 12 Jul 2025 15:28:40 +0100 Subject: [PATCH 23/62] Redirect InetPtonEx to InetPton --- src/core/libraries/network/net.cpp | 6 +++--- src/core/libraries/network/net.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/libraries/network/net.cpp b/src/core/libraries/network/net.cpp index 22fec11e9..4a76f5b41 100644 --- a/src/core/libraries/network/net.cpp +++ b/src/core/libraries/network/net.cpp @@ -1339,9 +1339,9 @@ int PS4_SYSV_ABI sceNetInetPton(int af, const char* src, void* dst) { return res; } -int PS4_SYSV_ABI sceNetInetPtonEx() { - LOG_ERROR(Lib_Net, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceNetInetPtonEx(int af, const char* src, void* dst, int flags) { + LOG_WARNING(Lib_Net, "ignored flags, redirecting to sceNetInetPton"); + return sceNetInetPton(af, src, dst); } int PS4_SYSV_ABI sceNetInetPtonWithScopeId() { diff --git a/src/core/libraries/network/net.h b/src/core/libraries/network/net.h index 2b7d42cfe..b3c93d7d9 100644 --- a/src/core/libraries/network/net.h +++ b/src/core/libraries/network/net.h @@ -297,7 +297,7 @@ u16 PS4_SYSV_ABI sceNetHtons(u16 host16); const char* PS4_SYSV_ABI sceNetInetNtop(int af, const void* src, char* dst, u32 size); int PS4_SYSV_ABI sceNetInetNtopWithScopeId(); int PS4_SYSV_ABI sceNetInetPton(int af, const char* src, void* dst); -int PS4_SYSV_ABI sceNetInetPtonEx(); +int PS4_SYSV_ABI sceNetInetPtonEx(int af, const char* src, void* dst, int flags); int PS4_SYSV_ABI sceNetInetPtonWithScopeId(); int PS4_SYSV_ABI sceNetInfoDumpStart(); int PS4_SYSV_ABI sceNetInfoDumpStop(); From 82ed8bb43f908e4e41aa77005f392e91e5365ddb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Sat, 12 Jul 2025 15:42:56 +0100 Subject: [PATCH 24/62] Redirect ResolverStartNtoaMultipleRecords --- src/core/libraries/network/net.cpp | 22 +++++++++++++++++++--- src/core/libraries/network/net.h | 21 ++++++++++++++++++++- 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/core/libraries/network/net.cpp b/src/core/libraries/network/net.cpp index 4a76f5b41..e3230a49e 100644 --- a/src/core/libraries/network/net.cpp +++ b/src/core/libraries/network/net.cpp @@ -1686,9 +1686,25 @@ int PS4_SYSV_ABI sceNetResolverStartNtoa6() { return ORBIS_OK; } -int PS4_SYSV_ABI sceNetResolverStartNtoaMultipleRecords() { - LOG_ERROR(Lib_Net, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceNetResolverStartNtoaMultipleRecords(OrbisNetId resolverid, const char* hostname, + OrbisNetResolverInfo* info, int timeout, int retry, int flags) { + LOG_WARNING(Lib_Net, "redirected to sceNetResolverStartNtoa"); + + OrbisNetInAddr addr{}; + auto result = sceNetResolverStartNtoa(resolverid, hostname, &addr, timeout, retry, flags); + + if (result == ORBIS_OK) { + info->addrs[0] = { + .u = { + .addr = addr + }, + .af = ORBIS_NET_AF_INET + }; + info->records = 1; + info->recordsv4 = 1; + } + + return result; } int PS4_SYSV_ABI sceNetResolverStartNtoaMultipleRecordsEx() { diff --git a/src/core/libraries/network/net.h b/src/core/libraries/network/net.h index b3c93d7d9..8aa2a7c0e 100644 --- a/src/core/libraries/network/net.h +++ b/src/core/libraries/network/net.h @@ -152,6 +152,24 @@ struct OrbisNetEpollEvent { OrbisNetEpollData data; }; +union OrbisNetAddrUnion { + OrbisNetInAddr addr; + u8 addr6[16]; +}; + +struct OrbisNetResolverAddr { + OrbisNetAddrUnion u; + u32 af; + u32 pad[3]; +}; + +struct OrbisNetResolverInfo { + OrbisNetResolverAddr addrs[10]; + u32 records; + u32 recordsv4; + u32 pad[14]; +}; + int PS4_SYSV_ABI in6addr_any(); int PS4_SYSV_ABI in6addr_loopback(); int PS4_SYSV_ABI sce_net_dummy(); @@ -331,7 +349,8 @@ int PS4_SYSV_ABI sceNetResolverStartAton6(); int PS4_SYSV_ABI sceNetResolverStartNtoa(OrbisNetId resolverid, const char* hostname, OrbisNetInAddr* addr, int timeout, int retry, int flags); int PS4_SYSV_ABI sceNetResolverStartNtoa6(); -int PS4_SYSV_ABI sceNetResolverStartNtoaMultipleRecords(); +int PS4_SYSV_ABI sceNetResolverStartNtoaMultipleRecords(OrbisNetId resolverid, const char* hostname, + OrbisNetResolverInfo* info, int timeout, int retry, int flags); int PS4_SYSV_ABI sceNetResolverStartNtoaMultipleRecordsEx(); int PS4_SYSV_ABI sceNetSend(OrbisNetId s, const void* buf, u64 len, int flags); int PS4_SYSV_ABI sceNetSendmsg(OrbisNetId s, const OrbisNetMsghdr* msg, int flags); From d9920706387ff8546348fa62973f653a55ee25f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Sat, 12 Jul 2025 15:44:15 +0100 Subject: [PATCH 25/62] Register sys_getsockopt to libScePosix --- src/core/libraries/network/net.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/libraries/network/net.cpp b/src/core/libraries/network/net.cpp index e3230a49e..af0839c02 100644 --- a/src/core/libraries/network/net.cpp +++ b/src/core/libraries/network/net.cpp @@ -2398,6 +2398,7 @@ void RegisterLib(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("Cidi9Y65mP8", "libSceNet", 1, "libSceNet", 1, 1, sceNetGetSockInfo6); LIB_FUNCTION("hoOAofhhRvE", "libSceNet", 1, "libSceNet", 1, 1, sceNetGetsockname); LIB_FUNCTION("xphrZusl78E", "libSceNet", 1, "libSceNet", 1, 1, sceNetGetsockopt); + LIB_FUNCTION("6O8EwYOgH9Y", "libScePosix", 1, "libkernel", 1, 1, sys_getsockopt); LIB_FUNCTION("GA5ZDaLtUBE", "libSceNet", 1, "libSceNet", 1, 1, sceNetGetStatisticsInfo); LIB_FUNCTION("9mIcUExH34w", "libSceNet", 1, "libSceNet", 1, 1, sceNetGetStatisticsInfoInternal); LIB_FUNCTION("p2vxsE2U3RQ", "libSceNet", 1, "libSceNet", 1, 1, sceNetGetSystemTime); From 71d38669c22cfed9b4254ee32acc6a334049bac3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Sat, 12 Jul 2025 15:49:12 +0100 Subject: [PATCH 26/62] Include socket field in the File struct --- src/core/file_sys/fs.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/core/file_sys/fs.h b/src/core/file_sys/fs.h index 4a2aa56c1..19f2fa876 100644 --- a/src/core/file_sys/fs.h +++ b/src/core/file_sys/fs.h @@ -11,6 +11,7 @@ #include "common/io_file.h" #include "common/logging/formatter.h" #include "core/devices/base_device.h" +#include "core/libraries/network/sockets.h" namespace Core::FileSys { @@ -77,6 +78,7 @@ enum class FileType { Regular, // standard file Directory, Device, + Socket, }; struct File { @@ -89,6 +91,7 @@ struct File { u32 dirents_index; std::mutex m_mutex; std::shared_ptr device; // only valid for type == Device + std::shared_ptr socket; // only valid for type == Socket }; class HandleTable { From 80a6ce02510956efd58a03dbddd299ecdc402ea8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Sat, 12 Jul 2025 16:11:32 +0100 Subject: [PATCH 27/62] Register sockets in the file descriptors table --- src/core/libraries/kernel/file_system.cpp | 16 ++++ src/core/libraries/kernel/kernel.cpp | 7 +- src/core/libraries/network/net.cpp | 9 +- src/core/libraries/network/sys_net.cpp | 100 +++++++++++++--------- 4 files changed, 89 insertions(+), 43 deletions(-) diff --git a/src/core/libraries/kernel/file_system.cpp b/src/core/libraries/kernel/file_system.cpp index a2d9cc93f..44d2c3d46 100644 --- a/src/core/libraries/kernel/file_system.cpp +++ b/src/core/libraries/kernel/file_system.cpp @@ -257,6 +257,8 @@ s32 PS4_SYSV_ABI close(s32 fd) { } if (file->type == Core::FileSys::FileType::Regular) { file->f.Close(); + } else if (file->type == Core::FileSys::FileType::Regular) { + file->socket->Close(); } file->is_opened = false; LOG_INFO(Kernel_Fs, "Closing {}", file->m_guest_name); @@ -294,6 +296,13 @@ s64 PS4_SYSV_ABI write(s32 fd, const void* buf, size_t nbytes) { return -1; } return result; + } else if (file->type == Core::FileSys::FileType::Socket) { + s64 result = ::write(file->socket->Native(), buf, nbytes); + if (result < 0) { + ErrSceToPosix(result); + return -1; + } + return result; } return file->f.WriteRaw(buf, nbytes); @@ -475,6 +484,13 @@ s64 PS4_SYSV_ABI read(s32 fd, void* buf, size_t nbytes) { return -1; } return result; + } else if (file->type == Core::FileSys::FileType::Socket) { + s64 result = ::read(file->socket->Native(), buf, nbytes); + if (result < 0) { + ErrSceToPosix(result); + return -1; + } + return result; } return ReadFile(file->f, buf, nbytes); } diff --git a/src/core/libraries/kernel/kernel.cpp b/src/core/libraries/kernel/kernel.cpp index 928b6c14b..f72fcd9e0 100644 --- a/src/core/libraries/kernel/kernel.cpp +++ b/src/core/libraries/kernel/kernel.cpp @@ -216,13 +216,14 @@ s32 PS4_SYSV_ABI posix_getpagesize() { s32 PS4_SYSV_ABI posix_getsockname(Libraries::Net::OrbisNetId s, Libraries::Net::OrbisNetSockaddr* addr, u32* paddrlen) { LOG_DEBUG(Lib_Net, "s = {}", s); - auto* netcall = Common::Singleton::Instance(); - auto sock = netcall->FindSocket(s); - if (!sock) { + auto* h = Common::Singleton::Instance(); + auto* file = h->GetFile(s); + if (!file || file->type != Core::FileSys::FileType::Socket) { *Libraries::Kernel::__Error() = ORBIS_NET_ERROR_EBADF; LOG_ERROR(Lib_Net, "socket id is invalid = {}", s); return -1; } + auto sock = file->socket; s32 returncode = sock->GetSocketAddress(addr, paddrlen); if (returncode >= 0) { LOG_DEBUG(Lib_Net, "return code : {:#x}", (u32)returncode); diff --git a/src/core/libraries/network/net.cpp b/src/core/libraries/network/net.cpp index af0839c02..515b40a74 100644 --- a/src/core/libraries/network/net.cpp +++ b/src/core/libraries/network/net.cpp @@ -16,6 +16,7 @@ #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" @@ -761,7 +762,13 @@ int PS4_SYSV_ABI sceNetEpollControl(OrbisNetId epollid, OrbisNetEpollFlag op, Or } #ifdef __linux__ - const auto socket = Common::Singleton::Instance()->socks[id]; + // const auto socket = Common::Singleton::Instance()->socks[id]; + auto* h = Common::Singleton::Instance(); + auto* file = h->GetFile(id); + if (!file || file->type != Core::FileSys::FileType::Socket) { + return -ORBIS_NET_EBADF; + } + const auto socket = file->socket; epoll_event native_event = {.events = ConvertEpollEventsIn(event->events), .data = {.fd = id}}; ASSERT(epoll_ctl(epolls[epollid].epoll_fd, EPOLL_CTL_ADD, socket->Native(), diff --git a/src/core/libraries/network/sys_net.cpp b/src/core/libraries/network/sys_net.cpp index 012f8b59b..708fc9f4d 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 "core/file_sys/fs.h" #include "common/error.h" #include "common/singleton.h" #include "net_error.h" @@ -15,13 +16,14 @@ namespace Libraries::Net { int PS4_SYSV_ABI sys_connect(OrbisNetId s, const OrbisNetSockaddr* addr, u32 addrlen) { LOG_WARNING(Lib_Net, "s = {}", s); - auto* netcall = Common::Singleton::Instance(); - auto sock = netcall->FindSocket(s); - if (!sock) { + auto* h = Common::Singleton::Instance(); + auto* file = h->GetFile(s); + if (!file || file->type != Core::FileSys::FileType::Socket) { *Libraries::Kernel::__Error() = ORBIS_NET_ERROR_EBADF; LOG_ERROR(Lib_Net, "socket id is invalid = {}", s); return -1; } + auto sock = file->socket; int returncode = sock->Connect(addr, addrlen); if (returncode >= 0) { return returncode; @@ -34,13 +36,14 @@ int PS4_SYSV_ABI sys_bind(OrbisNetId s, const OrbisNetSockaddr* addr, u32 addrle LOG_DEBUG(Lib_Net, "s = {}, addr = {:#x}, addrlen = {}", s, reinterpret_cast(addr), addrlen); - auto* netcall = Common::Singleton::Instance(); - auto sock = netcall->FindSocket(s); - if (!sock) { + auto* h = Common::Singleton::Instance(); + auto* file = h->GetFile(s); + if (!file || file->type != Core::FileSys::FileType::Socket) { *Libraries::Kernel::__Error() = ORBIS_NET_ERROR_EBADF; LOG_ERROR(Lib_Net, "socket id is invalid = {}", s); return -1; } + auto sock = file->socket; int returncode = sock->Bind(addr, addrlen); if (returncode >= 0) { return returncode; @@ -52,13 +55,14 @@ int PS4_SYSV_ABI sys_bind(OrbisNetId s, const OrbisNetSockaddr* addr, u32 addrle int PS4_SYSV_ABI sys_accept(OrbisNetId s, OrbisNetSockaddr* addr, u32* paddrlen) { LOG_WARNING(Lib_Net, "(DUMMY) called"); - auto* netcall = Common::Singleton::Instance(); - auto sock = netcall->FindSocket(s); - if (!sock) { - *Libraries::Kernel::__Error() = ORBIS_NET_EBADF; + auto* h = Common::Singleton::Instance(); + auto* file = h->GetFile(s); + if (!file || file->type != Core::FileSys::FileType::Socket) { + *Libraries::Kernel::__Error() = ORBIS_NET_ERROR_EBADF; LOG_ERROR(Lib_Net, "socket id is invalid = {}", s); return -1; } + auto sock = file->socket; auto new_sock = sock->Accept(addr, paddrlen); if (!new_sock) { *Libraries::Kernel::__Error() = ORBIS_NET_EBADF; @@ -66,9 +70,12 @@ int PS4_SYSV_ABI sys_accept(OrbisNetId s, OrbisNetSockaddr* addr, u32* paddrlen) Common::GetLastErrorMsg()); return -1; } - auto id = ++netcall->next_sock_id; - netcall->socks.emplace(id, new_sock); - return id; + u32 handle = h->CreateHandle(); + auto* new_file = h->GetFile(handle); + new_file->is_opened = true; + new_file->type = Core::FileSys::FileType::Socket; + new_file->socket = new_sock; + return handle; } int PS4_SYSV_ABI sys_getpeername(OrbisNetId s, const OrbisNetSockaddr* addr, u32* paddrlen) { LOG_ERROR(Lib_Net, "(STUBBED) called"); @@ -77,13 +84,14 @@ int PS4_SYSV_ABI sys_getpeername(OrbisNetId s, const OrbisNetSockaddr* addr, u32 int PS4_SYSV_ABI sys_getsockname(OrbisNetId s, OrbisNetSockaddr* addr, u32* paddrlen) { LOG_WARNING(Lib_Net, "(DUMMY) called"); - auto* netcall = Common::Singleton::Instance(); - auto sock = netcall->FindSocket(s); - if (!sock) { + auto* h = Common::Singleton::Instance(); + auto* file = h->GetFile(s); + if (!file || file->type != Core::FileSys::FileType::Socket) { *Libraries::Kernel::__Error() = ORBIS_NET_ERROR_EBADF; LOG_ERROR(Lib_Net, "socket id is invalid = {}", s); return -1; } + auto sock = file->socket; int returncode = sock->GetSocketAddress(addr, paddrlen); if (returncode >= 0) { return returncode; @@ -95,13 +103,14 @@ int PS4_SYSV_ABI sys_getsockname(OrbisNetId s, OrbisNetSockaddr* addr, u32* padd int PS4_SYSV_ABI sys_getsockopt(OrbisNetId s, int level, int optname, void* optval, u32* optlen) { LOG_WARNING(Lib_Net, "(DUMMY) called"); - auto* netcall = Common::Singleton::Instance(); - auto sock = netcall->FindSocket(s); - if (!sock) { + auto* h = Common::Singleton::Instance(); + auto* file = h->GetFile(s); + if (!file || file->type != Core::FileSys::FileType::Socket) { *Libraries::Kernel::__Error() = ORBIS_NET_ERROR_EBADF; LOG_ERROR(Lib_Net, "socket id is invalid = {}", s); return -1; } + auto sock = file->socket; int returncode = sock->GetSocketOptions(level, optname, optval, optlen); if (returncode >= 0) { return returncode; @@ -113,13 +122,14 @@ int PS4_SYSV_ABI sys_getsockopt(OrbisNetId s, int level, int optname, void* optv int PS4_SYSV_ABI sys_listen(OrbisNetId s, int backlog) { LOG_DEBUG(Lib_Net, "s = {}, backlog = {}", s, backlog); - auto* netcall = Common::Singleton::Instance(); - auto sock = netcall->FindSocket(s); - if (!sock) { + auto* h = Common::Singleton::Instance(); + auto* file = h->GetFile(s); + if (!file || file->type != Core::FileSys::FileType::Socket) { *Libraries::Kernel::__Error() = ORBIS_NET_ERROR_EBADF; LOG_ERROR(Lib_Net, "socket id is invalid = {}", s); return -1; } + auto sock = file->socket; int returncode = sock->Listen(backlog); if (returncode >= 0) { return returncode; @@ -133,13 +143,14 @@ int PS4_SYSV_ABI sys_setsockopt(OrbisNetId s, int level, int optname, const void u32 optlen) { LOG_WARNING(Lib_Net, "netId = {}", s); - auto* netcall = Common::Singleton::Instance(); - auto sock = netcall->FindSocket(s); - if (!sock) { + auto* h = Common::Singleton::Instance(); + auto* file = h->GetFile(s); + if (!file || file->type != Core::FileSys::FileType::Socket) { *Libraries::Kernel::__Error() = ORBIS_NET_ERROR_EBADF; LOG_ERROR(Lib_Net, "socket id is invalid = {}", s); return -1; } + auto sock = file->socket; int returncode = sock->SetSocketOptions(level, optname, optval, optlen); LOG_INFO(Lib_Net, "returncode = {}", returncode); if (returncode >= 0) { @@ -181,10 +192,16 @@ int PS4_SYSV_ABI sys_socketex(const char* name, int family, int type, int protoc default: UNREACHABLE_MSG("Unknown type {}", type); } - auto* netcall = Common::Singleton::Instance(); - auto id = ++netcall->next_sock_id; - netcall->socks.emplace(id, sock); - return id; + auto* h = Common::Singleton::Instance(); + u32 handle = h->CreateHandle(); + auto* file = h->GetFile(handle); + file->is_opened = true; + file->type = Core::FileSys::FileType::Socket; + file->socket = sock; + // auto* netcall = Common::Singleton::Instance(); + // auto id = ++netcall->next_sock_id; + // netcall->socks.emplace(id, sock); + return handle; } int PS4_SYSV_ABI sys_socket(int family, int type, int protocol) { return sys_socketex(nullptr, family, type, protocol); @@ -194,16 +211,19 @@ int PS4_SYSV_ABI sys_netabort(OrbisNetId s, int flags) { return -1; } int PS4_SYSV_ABI sys_socketclose(OrbisNetId s) { - LOG_WARNING(Lib_Net, "(DUMMY) called"); + LOG_INFO(Lib_Net, "called, s = {}", s); - auto* netcall = Common::Singleton::Instance(); - auto sock = netcall->FindSocket(s); - if (!sock) { + auto* h = Common::Singleton::Instance(); + auto* file = h->GetFile(s); + if (!file || file->type != Core::FileSys::FileType::Socket) { *Libraries::Kernel::__Error() = ORBIS_NET_ERROR_EBADF; LOG_ERROR(Lib_Net, "socket id is invalid = {}", s); return -1; } + auto sock = file->socket; + file->is_opened = false; int returncode = sock->Close(); + h->DeleteHandle(s); if (returncode >= 0) { return returncode; } @@ -215,13 +235,14 @@ int PS4_SYSV_ABI sys_sendto(OrbisNetId s, const void* buf, u64 len, int flags, const OrbisNetSockaddr* addr, u32 addrlen) { LOG_WARNING(Lib_Net, "s = {}, len = {}, flags = {:#x}, addrlen = {}", s, len, flags, addrlen); - auto* netcall = Common::Singleton::Instance(); - auto sock = netcall->FindSocket(s); - if (!sock) { + auto* h = Common::Singleton::Instance(); + auto* file = h->GetFile(s); + if (!file || file->type != Core::FileSys::FileType::Socket) { *Libraries::Kernel::__Error() = ORBIS_NET_ERROR_EBADF; LOG_ERROR(Lib_Net, "socket id is invalid = {}", s); return -1; } + auto sock = file->socket; int returncode = sock->SendPacket(buf, len, flags, addr, addrlen); if (returncode >= 0) { return returncode; @@ -239,13 +260,14 @@ int PS4_SYSV_ABI sys_recvfrom(OrbisNetId s, void* buf, u64 len, int flags, Orbis // LOG_INFO(Lib_Net, "s = {}, buf = {:#x}, len = {}, flags = {:#x}", s, // reinterpret_cast(buf), len, flags); - auto* netcall = Common::Singleton::Instance(); - auto sock = netcall->FindSocket(s); - if (!sock) { + auto* h = Common::Singleton::Instance(); + auto* file = h->GetFile(s); + if (!file || file->type != Core::FileSys::FileType::Socket) { *Libraries::Kernel::__Error() = ORBIS_NET_ERROR_EBADF; LOG_ERROR(Lib_Net, "socket id is invalid = {}", s); return -1; } + auto sock = file->socket; int returncode = sock->ReceivePacket(buf, len, flags, addr, paddrlen); if (returncode >= 0) { return returncode; From 334bf68b32a545cccfe0f85f6f6485f4eca0582f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Sat, 12 Jul 2025 16:19:10 +0100 Subject: [PATCH 28/62] Handle sockets in fstat --- src/core/libraries/kernel/file_system.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/core/libraries/kernel/file_system.cpp b/src/core/libraries/kernel/file_system.cpp index 44d2c3d46..0e377a106 100644 --- a/src/core/libraries/kernel/file_system.cpp +++ b/src/core/libraries/kernel/file_system.cpp @@ -23,6 +23,8 @@ #include "core/memory.h" #include "kernel.h" +#include + namespace D = Core::Devices; using FactoryDevice = std::function(u32, const char*, int, u16)>; @@ -683,6 +685,20 @@ s32 PS4_SYSV_ABI fstat(s32 fd, OrbisKernelStat* sb) { // TODO incomplete break; } + case Core::FileSys::FileType::Socket: { + struct stat st{}; + s32 result = ::fstat(file->socket->Native(), &st); + if (result < 0) { + ErrSceToPosix(result); + return -1; + } + sb->st_mode = 0000777u | 0140000u; + sb->st_size = st.st_size; + sb->st_blocks = st.st_blocks; + sb->st_blksize = st.st_blksize; + // sb->st_flags = st.st_flags; + break; + } default: UNREACHABLE(); } From 4d0fa375ad373c2cc7e10e79eeac381666943aff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Sat, 12 Jul 2025 16:20:35 +0100 Subject: [PATCH 29/62] Call native select --- src/core/libraries/kernel/file_system.cpp | 89 ++++++++++++++++++++++- 1 file changed, 88 insertions(+), 1 deletion(-) diff --git a/src/core/libraries/kernel/file_system.cpp b/src/core/libraries/kernel/file_system.cpp index 0e377a106..89f0121ac 100644 --- a/src/core/libraries/kernel/file_system.cpp +++ b/src/core/libraries/kernel/file_system.cpp @@ -23,6 +23,7 @@ #include "core/memory.h" #include "kernel.h" +#include #include namespace D = Core::Devices; @@ -1095,7 +1096,93 @@ s32 PS4_SYSV_ABI posix_select(int nfds, fd_set* readfds, fd_set* writefds, fd_se nfds, reinterpret_cast(readfds), reinterpret_cast(writefds), reinterpret_cast(exceptfds), reinterpret_cast(timeout)); - return ORBIS_OK; + LOG_INFO(Kernel_Fs, "nfds = {}", nfds); + + fd_set read_host, write_host, except_host; + FD_ZERO(&read_host); + FD_ZERO(&write_host); + FD_ZERO(&except_host); + std::map host_to_guest; + + auto* h = Common::Singleton::Instance(); + int max_fd = 0; + + for (auto i = 0; i < nfds; ++i) { + auto read = readfds && FD_ISSET(i, readfds); + auto write = writefds && FD_ISSET(i, writefds); + auto except = exceptfds && FD_ISSET(i, exceptfds); + if (read || write || except) { + LOG_INFO(Kernel_Fs, "guest fd {} expected", i); + auto* file = h->GetFile(i); + if (file == nullptr || + ((file->type == Core::FileSys::FileType::Regular && !file->f.IsOpen()) || + (file->type == Core::FileSys::FileType::Socket && !file->is_opened))) { + LOG_ERROR(Kernel_Fs, "fd {} is null or not opened", i); + *__Error() = POSIX_EBADF; + return -1; + } + + int fd = [&] { + switch (file->type) { + case Core::FileSys::FileType::Regular: + return static_cast(file->f.GetFileMapping()); + case Core::FileSys::FileType::Socket: + return file->socket->Native(); + default: + UNREACHABLE(); + } + }(); + host_to_guest.emplace(fd, i); + + max_fd = std::max(max_fd, fd); + + if (read) { + FD_SET(fd, &read_host); + continue; + } + if (write) { + FD_SET(fd, &write_host); + continue; + } + if (except) { + FD_SET(fd, &except_host); + continue; + } + } + } + + LOG_INFO(Kernel_Fs, "calling select"); + int ret = select(max_fd + 1, &read_host, &write_host, &except_host, (timeval*)timeout); + LOG_INFO(Kernel_Fs, "select = {}", ret); + + if (ret > 0) { + if (readfds) { + FD_ZERO(readfds); + } + if (writefds) { + FD_ZERO(writefds); + } + if (exceptfds) { + FD_ZERO(exceptfds); + } + + for (auto i = 0; i < max_fd + 1; ++i) { + if (FD_ISSET(i, &read_host)) { + LOG_INFO(Kernel_Fs, "host fd {} (guest {}) ready for reading", i, host_to_guest[i]); + FD_SET(host_to_guest[i], readfds); + } + if (FD_ISSET(i, &write_host)) { + LOG_INFO(Kernel_Fs, "host fd {} (guest {}) ready for writing", i, host_to_guest[i]); + FD_SET(host_to_guest[i], writefds); + } + if (FD_ISSET(i, &except_host)) { + LOG_INFO(Kernel_Fs, "host fd {} (guest {}) ready for except", i, host_to_guest[i]); + FD_SET(host_to_guest[i], exceptfds); + } + } + } + + return ret; } void RegisterFileSystem(Core::Loader::SymbolsResolver* sym) { From 31a708934c1cf0958ec56e5d333677494b906e3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Sat, 12 Jul 2025 16:22:06 +0100 Subject: [PATCH 30/62] clang-format --- src/core/file_sys/fs.h | 2 +- src/core/libraries/network/net.cpp | 10 +++------- src/core/libraries/network/net.h | 3 ++- src/core/libraries/network/sys_net.cpp | 2 +- 4 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/core/file_sys/fs.h b/src/core/file_sys/fs.h index 19f2fa876..714405493 100644 --- a/src/core/file_sys/fs.h +++ b/src/core/file_sys/fs.h @@ -90,7 +90,7 @@ struct File { std::vector dirents; u32 dirents_index; std::mutex m_mutex; - std::shared_ptr device; // only valid for type == Device + std::shared_ptr device; // only valid for type == Device std::shared_ptr socket; // only valid for type == Socket }; diff --git a/src/core/libraries/network/net.cpp b/src/core/libraries/network/net.cpp index 515b40a74..7c6e7ef40 100644 --- a/src/core/libraries/network/net.cpp +++ b/src/core/libraries/network/net.cpp @@ -1694,19 +1694,15 @@ int PS4_SYSV_ABI sceNetResolverStartNtoa6() { } int PS4_SYSV_ABI sceNetResolverStartNtoaMultipleRecords(OrbisNetId resolverid, const char* hostname, - OrbisNetResolverInfo* info, int timeout, int retry, int flags) { + OrbisNetResolverInfo* info, int timeout, + int retry, int flags) { LOG_WARNING(Lib_Net, "redirected to sceNetResolverStartNtoa"); OrbisNetInAddr addr{}; auto result = sceNetResolverStartNtoa(resolverid, hostname, &addr, timeout, retry, flags); if (result == ORBIS_OK) { - info->addrs[0] = { - .u = { - .addr = addr - }, - .af = ORBIS_NET_AF_INET - }; + info->addrs[0] = {.u = {.addr = addr}, .af = ORBIS_NET_AF_INET}; info->records = 1; info->recordsv4 = 1; } diff --git a/src/core/libraries/network/net.h b/src/core/libraries/network/net.h index 8aa2a7c0e..064106f6f 100644 --- a/src/core/libraries/network/net.h +++ b/src/core/libraries/network/net.h @@ -350,7 +350,8 @@ int PS4_SYSV_ABI sceNetResolverStartNtoa(OrbisNetId resolverid, const char* host OrbisNetInAddr* addr, int timeout, int retry, int flags); int PS4_SYSV_ABI sceNetResolverStartNtoa6(); int PS4_SYSV_ABI sceNetResolverStartNtoaMultipleRecords(OrbisNetId resolverid, const char* hostname, - OrbisNetResolverInfo* info, int timeout, int retry, int flags); + OrbisNetResolverInfo* info, int timeout, + int retry, int flags); int PS4_SYSV_ABI sceNetResolverStartNtoaMultipleRecordsEx(); int PS4_SYSV_ABI sceNetSend(OrbisNetId s, const void* buf, u64 len, int flags); int PS4_SYSV_ABI sceNetSendmsg(OrbisNetId s, const OrbisNetMsghdr* msg, int flags); diff --git a/src/core/libraries/network/sys_net.cpp b/src/core/libraries/network/sys_net.cpp index 708fc9f4d..749f0efde 100644 --- a/src/core/libraries/network/sys_net.cpp +++ b/src/core/libraries/network/sys_net.cpp @@ -4,9 +4,9 @@ #include #include #include -#include "core/file_sys/fs.h" #include "common/error.h" #include "common/singleton.h" +#include "core/file_sys/fs.h" #include "net_error.h" #include "sockets.h" #include "sys_net.h" From 7687c9aa38fad4a565713d324721f75365dfc459 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Sat, 12 Jul 2025 17:03:10 +0100 Subject: [PATCH 31/62] Bump config entries --- src/common/config.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/config.cpp b/src/common/config.cpp index 0d73a7f5e..9caccac4d 100644 --- a/src/common/config.cpp +++ b/src/common/config.cpp @@ -108,7 +108,7 @@ u32 m_language = 1; // english static std::string trophyKey = ""; // Expected number of items in the config file -static constexpr u64 total_entries = 54; +static constexpr u64 total_entries = 55; int getVolumeSlider() { return volumeSlider; From 97946ca3a5e751d847c443be0d7a833156944456 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Sat, 12 Jul 2025 17:05:26 +0100 Subject: [PATCH 32/62] Register sys_getpeername to libScePosix --- src/core/libraries/network/net.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/libraries/network/net.cpp b/src/core/libraries/network/net.cpp index 7c6e7ef40..06d68314d 100644 --- a/src/core/libraries/network/net.cpp +++ b/src/core/libraries/network/net.cpp @@ -2395,6 +2395,7 @@ void RegisterLib(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("rMyh97BU5pY", "libSceNet", 1, "libSceNet", 1, 1, sceNetGetMemoryPoolStats); LIB_FUNCTION("+S-2-jlpaBo", "libSceNet", 1, "libSceNet", 1, 1, sceNetGetNameToIndex); LIB_FUNCTION("TCkRD0DWNLg", "libSceNet", 1, "libSceNet", 1, 1, sceNetGetpeername); + LIB_FUNCTION("TXFFFiNldU8", "libScePosix", 1, "libkernel", 1, 1, sys_getpeername); LIB_FUNCTION("G3O2j9f5z00", "libSceNet", 1, "libSceNet", 1, 1, sceNetGetRandom); LIB_FUNCTION("6Nx1hIQL9h8", "libSceNet", 1, "libSceNet", 1, 1, sceNetGetRouteInfo); LIB_FUNCTION("hLuXdjHnhiI", "libSceNet", 1, "libSceNet", 1, 1, sceNetGetSockInfo); From 296e4a0019d646d08809224656ee47983b4e04b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Sat, 12 Jul 2025 17:15:58 +0100 Subject: [PATCH 33/62] Implement sys_getpeername --- src/core/libraries/network/p2p_sockets.cpp | 5 +++++ src/core/libraries/network/posix_sockets.cpp | 17 ++++++++++++++++ src/core/libraries/network/sockets.h | 3 +++ src/core/libraries/network/sys_net.cpp | 21 ++++++++++++++++++-- src/core/libraries/network/sys_net.h | 2 +- 5 files changed, 45 insertions(+), 3 deletions(-) diff --git a/src/core/libraries/network/p2p_sockets.cpp b/src/core/libraries/network/p2p_sockets.cpp index 4f678dace..796a4c562 100644 --- a/src/core/libraries/network/p2p_sockets.cpp +++ b/src/core/libraries/network/p2p_sockets.cpp @@ -57,4 +57,9 @@ int P2PSocket::GetSocketAddress(OrbisNetSockaddr* name, u32* namelen) { return 0; } +int P2PSocket::GetPeerName(OrbisNetSockaddr* addr, u32* namelen) { + LOG_ERROR(Lib_Net, "(STUBBED) called"); + return 0; +} + } // 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 1266ca86b..2142adc3c 100644 --- a/src/core/libraries/network/posix_sockets.cpp +++ b/src/core/libraries/network/posix_sockets.cpp @@ -273,6 +273,23 @@ int PosixSocket::GetSocketAddress(OrbisNetSockaddr* name, u32* namelen) { return res; } +int PosixSocket::GetPeerName(OrbisNetSockaddr* name, u32* namelen) { + std::scoped_lock lock{m_mutex}; + LOG_DEBUG(Lib_Net, "called"); + + sockaddr addr; + convertOrbisNetSockaddrToPosix(name, &addr); + if (name != nullptr) { + *namelen = sizeof(sockaddr_in); + } + int res = ::getpeername(sock, &addr, (socklen_t*)namelen); + if (res >= 0) { + convertPosixSockaddrToOrbis(&addr, name); + *namelen = sizeof(OrbisNetSockaddrIn); + } + return res; +} + #define CASE_SETSOCKOPT(opt) \ case ORBIS_NET_##opt: \ return ConvertReturnErrorCode(setsockopt(sock, level, opt, (const char*)optval, optlen)) diff --git a/src/core/libraries/network/sockets.h b/src/core/libraries/network/sockets.h index 1d5485ef3..ce54ee765 100644 --- a/src/core/libraries/network/sockets.h +++ b/src/core/libraries/network/sockets.h @@ -51,6 +51,7 @@ struct Socket { u32* fromlen) = 0; virtual int Connect(const OrbisNetSockaddr* addr, u32 namelen) = 0; virtual int GetSocketAddress(OrbisNetSockaddr* name, u32* namelen) = 0; + virtual int GetPeerName(OrbisNetSockaddr* addr, u32* namelen) = 0; virtual bool IsValid() const = 0; virtual net_socket Native() const = 0; std::mutex m_mutex; @@ -80,6 +81,7 @@ struct PosixSocket : public Socket { SocketPtr Accept(OrbisNetSockaddr* addr, u32* addrlen) override; int Connect(const OrbisNetSockaddr* addr, u32 namelen) override; int GetSocketAddress(OrbisNetSockaddr* name, u32* namelen) override; + int GetPeerName(OrbisNetSockaddr* addr, u32* namelen) override; bool IsValid() const override { return sock != -1; } @@ -101,6 +103,7 @@ struct P2PSocket : public Socket { SocketPtr Accept(OrbisNetSockaddr* addr, u32* addrlen) override; int Connect(const OrbisNetSockaddr* addr, u32 namelen) override; int GetSocketAddress(OrbisNetSockaddr* name, u32* namelen) override; + int GetPeerName(OrbisNetSockaddr* addr, u32* namelen) override; bool IsValid() const override { return true; } diff --git a/src/core/libraries/network/sys_net.cpp b/src/core/libraries/network/sys_net.cpp index 749f0efde..f6db325ed 100644 --- a/src/core/libraries/network/sys_net.cpp +++ b/src/core/libraries/network/sys_net.cpp @@ -77,10 +77,27 @@ int PS4_SYSV_ABI sys_accept(OrbisNetId s, OrbisNetSockaddr* addr, u32* paddrlen) new_file->socket = new_sock; return handle; } -int PS4_SYSV_ABI sys_getpeername(OrbisNetId s, const OrbisNetSockaddr* addr, u32* paddrlen) { - LOG_ERROR(Lib_Net, "(STUBBED) called"); + +int PS4_SYSV_ABI sys_getpeername(OrbisNetId s, OrbisNetSockaddr* addr, u32* paddrlen) { + LOG_WARNING(Lib_Net, "(DUMMY) called"); + + auto* h = Common::Singleton::Instance(); + auto* file = h->GetFile(s); + if (!file || file->type != Core::FileSys::FileType::Socket) { + *Libraries::Kernel::__Error() = ORBIS_NET_ERROR_EBADF; + LOG_ERROR(Lib_Net, "socket id is invalid = {}", s); + return -1; + } + auto sock = file->socket; + int returncode = sock->GetPeerName(addr, paddrlen); + if (returncode >= 0) { + return returncode; + } + *Libraries::Kernel::__Error() = returncode; + LOG_ERROR(Lib_Net, "error code returned : {:#x}", (u32)returncode); return -1; } + int PS4_SYSV_ABI sys_getsockname(OrbisNetId s, OrbisNetSockaddr* addr, u32* paddrlen) { LOG_WARNING(Lib_Net, "(DUMMY) called"); diff --git a/src/core/libraries/network/sys_net.h b/src/core/libraries/network/sys_net.h index 4366ea0f8..c23152de1 100644 --- a/src/core/libraries/network/sys_net.h +++ b/src/core/libraries/network/sys_net.h @@ -11,7 +11,7 @@ namespace Libraries::Net { int PS4_SYSV_ABI sys_connect(OrbisNetId s, const OrbisNetSockaddr* addr, u32 addrlen); int PS4_SYSV_ABI sys_bind(OrbisNetId s, const OrbisNetSockaddr* addr, u32 addrlen); int PS4_SYSV_ABI sys_accept(OrbisNetId s, OrbisNetSockaddr* addr, u32* paddrlen); -int PS4_SYSV_ABI sys_getpeername(OrbisNetId s, const OrbisNetSockaddr* addr, u32* paddrlen); +int PS4_SYSV_ABI sys_getpeername(OrbisNetId s, OrbisNetSockaddr* addr, u32* paddrlen); int PS4_SYSV_ABI sys_getsockname(OrbisNetId s, OrbisNetSockaddr* addr, u32* paddrlen); int PS4_SYSV_ABI sys_getsockopt(OrbisNetId s, int level, int optname, void* optval, u32* optlen); int PS4_SYSV_ABI sys_listen(OrbisNetId s, int backlog); From 794a74ad923536a968559b82de100aac72f0ef13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Sat, 12 Jul 2025 19:10:57 +0100 Subject: [PATCH 34/62] Print connection data in log --- src/emulator.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/emulator.cpp b/src/emulator.cpp index 9485b0e23..7e6b36cf1 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -134,6 +134,8 @@ void Emulator::Run(std::filesystem::path file, const std::vector ar LOG_INFO(Config, "General LogType: {}", Config::getLogType()); LOG_INFO(Config, "General isNeo: {}", Config::isNeoModeConsole()); + LOG_INFO(Config, "General isConnectedToNetwork: {}", Config::getIsConnectedToNetwork()); + LOG_INFO(Config, "General isPsnSignedIn: {}", Config::getPSNSignedIn()); LOG_INFO(Config, "GPU isNullGpu: {}", Config::nullGpu()); LOG_INFO(Config, "GPU readbacks: {}", Config::readbacks()); LOG_INFO(Config, "GPU readbackLinearImages: {}", Config::readbackLinearImages()); From b5e194096433feafd9ba3a117547f7542c7d21f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Sat, 12 Jul 2025 19:54:46 +0100 Subject: [PATCH 35/62] Handle IPv6 socket level in setsockopt --- src/core/libraries/network/net.h | 1 + src/core/libraries/network/posix_sockets.cpp | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/core/libraries/network/net.h b/src/core/libraries/network/net.h index 064106f6f..1912a9c5a 100644 --- a/src/core/libraries/network/net.h +++ b/src/core/libraries/network/net.h @@ -38,6 +38,7 @@ enum OrbisNetProtocol : u32 { ORBIS_NET_IPPROTO_IGMP = 2, ORBIS_NET_IPPROTO_TCP = 6, ORBIS_NET_IPPROTO_UDP = 17, + ORBIS_NET_IPPROTO_IPV6 = 41, ORBIS_NET_SOL_SOCKET = 0xFFFF }; diff --git a/src/core/libraries/network/posix_sockets.cpp b/src/core/libraries/network/posix_sockets.cpp index 2142adc3c..eddf1f2f9 100644 --- a/src/core/libraries/network/posix_sockets.cpp +++ b/src/core/libraries/network/posix_sockets.cpp @@ -128,8 +128,12 @@ static int ConvertLevels(int level) { return IPPROTO_IP; case ORBIS_NET_IPPROTO_TCP: return IPPROTO_TCP; + case ORBIS_NET_IPPROTO_UDP: + return IPPROTO_UDP; + case ORBIS_NET_IPPROTO_IPV6: + return IPPROTO_IPV6; default: - UNREACHABLE_MSG("{}", level); + UNREACHABLE_MSG("unhandled socket level {}", level); } } From 26687060cdf94610741a2de4cb25b7d9149f1642 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Sat, 12 Jul 2025 19:59:58 +0100 Subject: [PATCH 36/62] Rename fields not compiling with gcc --- src/core/libraries/network/net.cpp | 2 +- src/core/libraries/network/net.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/libraries/network/net.cpp b/src/core/libraries/network/net.cpp index 06d68314d..a7c2bd9a2 100644 --- a/src/core/libraries/network/net.cpp +++ b/src/core/libraries/network/net.cpp @@ -883,7 +883,7 @@ int PS4_SYSV_ABI sceNetEpollWait(OrbisNetId epollid, OrbisNetEpollEvent* events, .data = it->second.data, }; LOG_INFO(Lib_Net, "event[{}] = ( .events = {:#x}, .ident = {}, .data = {:#x} )", i, - events[i].events, events[i].ident, events[i].data.u64); + events[i].events, events[i].ident, events[i].data.data_u64); } return result; } diff --git a/src/core/libraries/network/net.h b/src/core/libraries/network/net.h index 1912a9c5a..3c29e9f30 100644 --- a/src/core/libraries/network/net.h +++ b/src/core/libraries/network/net.h @@ -141,9 +141,9 @@ struct OrbisNetMsghdr { union OrbisNetEpollData { void* ptr; - u32 u32; + u32 data_u32; int fd; - u64 u64; + u64 data_u64; }; struct OrbisNetEpollEvent { From c592b57a8139759ce1978f014d32056ec45038df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Sat, 12 Jul 2025 21:11:04 +0100 Subject: [PATCH 37/62] Include winsock2.h to access select --- src/core/libraries/kernel/file_system.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/core/libraries/kernel/file_system.cpp b/src/core/libraries/kernel/file_system.cpp index 89f0121ac..4a6938b10 100644 --- a/src/core/libraries/kernel/file_system.cpp +++ b/src/core/libraries/kernel/file_system.cpp @@ -23,7 +23,11 @@ #include "core/memory.h" #include "kernel.h" +#ifdef _WIN32 +#include +#else #include +#endif #include namespace D = Core::Devices; From a2855c4f3658350b16e80913e608b7c26e50e0fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Sat, 12 Jul 2025 22:42:18 +0100 Subject: [PATCH 38/62] Stub sceHttpsGetCaList --- src/core/libraries/network/http.cpp | 5 +++-- src/core/libraries/network/http.h | 5 ++++- src/core/libraries/network/ssl.h | 5 +++++ 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/core/libraries/network/http.cpp b/src/core/libraries/network/http.cpp index f7cbed931..7d43c61a5 100644 --- a/src/core/libraries/network/http.cpp +++ b/src/core/libraries/network/http.cpp @@ -492,8 +492,9 @@ int PS4_SYSV_ABI sceHttpsFreeCaList() { return ORBIS_OK; } -int PS4_SYSV_ABI sceHttpsGetCaList() { - LOG_ERROR(Lib_Http, "(STUBBED) called"); +int PS4_SYSV_ABI sceHttpsGetCaList(int httpCtxId, OrbisHttpsCaList* list) { + LOG_ERROR(Lib_Http, "(DUMMY) called, httpCtxId = {}", httpCtxId); + list->certsNum = 0; return ORBIS_OK; } diff --git a/src/core/libraries/network/http.h b/src/core/libraries/network/http.h index cc9ca57af..228080207 100644 --- a/src/core/libraries/network/http.h +++ b/src/core/libraries/network/http.h @@ -4,6 +4,7 @@ #pragma once #include "common/types.h" +#include "core/libraries/network/ssl.h" namespace Core::Loader { class SymbolsResolver; @@ -24,6 +25,8 @@ struct OrbisHttpUriElement { u8 reserved[10]; }; +using OrbisHttpsCaList = Libraries::Ssl::OrbisSslCaList; + int PS4_SYSV_ABI sceHttpAbortRequest(); int PS4_SYSV_ABI sceHttpAbortRequestForce(); int PS4_SYSV_ABI sceHttpAbortWaitRequest(); @@ -120,7 +123,7 @@ int PS4_SYSV_ABI sceHttpSetResponseHeaderMaxSize(); int PS4_SYSV_ABI sceHttpSetSendTimeOut(); int PS4_SYSV_ABI sceHttpSetSocketCreationCallback(); int PS4_SYSV_ABI sceHttpsFreeCaList(); -int PS4_SYSV_ABI sceHttpsGetCaList(); +int PS4_SYSV_ABI sceHttpsGetCaList(int httpCtxId, OrbisHttpsCaList* list); int PS4_SYSV_ABI sceHttpsGetSslError(); int PS4_SYSV_ABI sceHttpsLoadCert(); int PS4_SYSV_ABI sceHttpsSetMinSslVersion(); diff --git a/src/core/libraries/network/ssl.h b/src/core/libraries/network/ssl.h index f9827494a..fd55f528e 100644 --- a/src/core/libraries/network/ssl.h +++ b/src/core/libraries/network/ssl.h @@ -13,6 +13,11 @@ namespace Libraries::Ssl { struct OrbisSslCaCerts; +struct OrbisSslCaList { + void* certs; + int certsNum; +}; + int PS4_SYSV_ABI CA_MGMT_allocCertDistinguishedName(); int PS4_SYSV_ABI CA_MGMT_certDistinguishedNameCompare(); int PS4_SYSV_ABI CA_MGMT_convertKeyBlobToPKCS8Key(); From 62c0cc7d9abd88db33c1c04cac5538e3423e65a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Sat, 12 Jul 2025 22:43:20 +0100 Subject: [PATCH 39/62] Rename s_addr to fix windows compilation --- src/core/libraries/network/net.cpp | 2 +- src/core/libraries/network/net.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/libraries/network/net.cpp b/src/core/libraries/network/net.cpp index a7c2bd9a2..e4f1a8e0d 100644 --- a/src/core/libraries/network/net.cpp +++ b/src/core/libraries/network/net.cpp @@ -1681,7 +1681,7 @@ int PS4_SYSV_ABI sceNetResolverStartNtoa(OrbisNetId resolverid, const char* host ASSERT(info && info->ai_addr); in_addr resolved_addr = ((sockaddr_in*)info->ai_addr)->sin_addr; LOG_DEBUG(Lib_Net, "resolved address for {}: {}", hostname, inet_ntoa(resolved_addr)); - addr->s_addr = resolved_addr.s_addr; + addr->inaddr_addr = resolved_addr.s_addr; } freeaddrinfo(info); diff --git a/src/core/libraries/network/net.h b/src/core/libraries/network/net.h index 3c29e9f30..396bab42d 100644 --- a/src/core/libraries/network/net.h +++ b/src/core/libraries/network/net.h @@ -121,7 +121,7 @@ struct OrbisNetSockaddrIn { using OrbisNetInAddr_t = u32; struct OrbisNetInAddr { - OrbisNetInAddr_t s_addr; + OrbisNetInAddr_t inaddr_addr; }; struct OrbisNetIovec { From 9e14c72fe7f5b273a22919dec9713210d7878a2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Mon, 14 Jul 2025 19:22:01 +0100 Subject: [PATCH 40/62] Retrieve correct netmask in netctl --- src/core/libraries/network/net_util.cpp | 62 ++++++++++++++++++++++++- src/core/libraries/network/net_util.h | 3 ++ src/core/libraries/network/netctl.cpp | 11 +++++ 3 files changed, 75 insertions(+), 1 deletion(-) diff --git a/src/core/libraries/network/net_util.cpp b/src/core/libraries/network/net_util.cpp index d0f0a81da..e7b1bddcc 100644 --- a/src/core/libraries/network/net_util.cpp +++ b/src/core/libraries/network/net_util.cpp @@ -11,6 +11,7 @@ typedef int socklen_t; #else #include #include +#include #include #include #include @@ -21,7 +22,6 @@ typedef int socklen_t; typedef int net_socket; #endif #if defined(__APPLE__) -#include #include #endif @@ -100,6 +100,8 @@ bool NetUtilInternal::RetrieveEthernetAddr() { } } + close(sock); + if (success) { memcpy(ether_address.data(), ifr.ifr_hwaddr.sa_data, 6); return true; @@ -107,4 +109,62 @@ bool NetUtilInternal::RetrieveEthernetAddr() { #endif return false; } + +const std::string& NetUtilInternal::GetNetmask() const { + return netmask; +} + +bool NetUtilInternal::RetrieveNetmask() { + std::scoped_lock lock{m_mutex}; + char netmaskStr[INET_ADDRSTRLEN]; + auto success = false; + +#ifdef _WIN32 + std::vector adapter_addresses(sizeof(IP_ADAPTER_ADDRESSES)); + ULONG size_infos = sizeof(IP_ADAPTER_ADDRESSES); + + if (GetAdaptersInfo(reinterpret_cast(adapter_infos.data()), &size_infos) == + ERROR_BUFFER_OVERFLOW) + adapter_infos.resize(size_infos); + + if (GetAdaptersInfo(reinterpret_cast(adapter_infos.data()), &size_infos) == + NO_ERROR && size_infos) { + PIP_ADAPTER_ADDRESSES adapter; + for (adapter = adapter_addresses; adapter; adapter = adapter->Next) { + PIP_ADAPTER_UNICAST_ADDRESS unicast = adapter->FirstUnicastAddress; + if (unicast) { + ULONG prefix_length = unicast->OnLinkPrefixLength; + ULONG mask = prefix_length == 0 ? 0 : 0xFFFFFFFF << (32 - prefix_length); + in_addr addr{}; + addr.S_un.S_addr = htonl(mask); + inet_ntop(AF_INET, &addr, netmaskStr, INET_ADDRSTRLEN); + success = true; + } + } + } + +#else + ifaddrs* ifap; + + if (getifaddrs(&ifap) == 0) { + ifaddrs* p; + for (p = ifap; p; p = p->ifa_next) { + if (p->ifa_addr && p->ifa_addr->sa_family == AF_INET) { + auto sa = reinterpret_cast(p->ifa_netmask); + inet_ntop(AF_INET, &sa->sin_addr, netmaskStr, INET_ADDRSTRLEN); + success = true; + } + } + } + + freeifaddrs(ifap); +#endif + + if (success) { + netmask = netmaskStr; + } + return success; +} + + } // namespace NetUtil \ No newline at end of file diff --git a/src/core/libraries/network/net_util.h b/src/core/libraries/network/net_util.h index be9dc15a1..97f671705 100644 --- a/src/core/libraries/network/net_util.h +++ b/src/core/libraries/network/net_util.h @@ -15,10 +15,13 @@ public: private: std::array ether_address{}; + std::string netmask{}; std::mutex m_mutex; public: const std::array& GetEthernetAddr() const; + const std::string& GetNetmask() const; bool RetrieveEthernetAddr(); + bool RetrieveNetmask(); }; } // namespace NetUtil \ No newline at end of file diff --git a/src/core/libraries/network/netctl.cpp b/src/core/libraries/network/netctl.cpp index 32cab7c74..6c874b400 100644 --- a/src/core/libraries/network/netctl.cpp +++ b/src/core/libraries/network/netctl.cpp @@ -220,6 +220,17 @@ int PS4_SYSV_ABI sceNetCtlGetInfo(int code, OrbisNetCtlInfo* info) { case ORBIS_NET_CTL_INFO_DHCP_HOSTNAME: // info-> = ; break; + case ORBIS_NET_CTL_INFO_NETMASK: { + auto* netinfo = Common::Singleton::Instance(); + auto success = netinfo->RetrieveNetmask(); + if (success) { + strncpy(info->netmask, netinfo->GetNetmask().data(), sizeof(info->netmask)); + LOG_DEBUG(Lib_NetCtl, "netmask: {}", info->netmask); + } else { + LOG_WARNING(Lib_NetCtl, "netmask: failed to retrieve"); + } + break; + } default: LOG_ERROR(Lib_NetCtl, "{} unsupported code", code); } From 980732d65b36c91e197a72c7821419387e6b8ae3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Mon, 14 Jul 2025 19:44:54 +0100 Subject: [PATCH 41/62] Retrieve correct default route in netctl (Linux) --- src/core/libraries/network/net_util.cpp | 44 +++++++++++++++++++++++++ src/core/libraries/network/net_util.h | 3 ++ src/core/libraries/network/netctl.cpp | 13 ++++++-- 3 files changed, 58 insertions(+), 2 deletions(-) diff --git a/src/core/libraries/network/net_util.cpp b/src/core/libraries/network/net_util.cpp index e7b1bddcc..aaedcc12a 100644 --- a/src/core/libraries/network/net_util.cpp +++ b/src/core/libraries/network/net_util.cpp @@ -24,6 +24,11 @@ typedef int net_socket; #if defined(__APPLE__) #include #endif +#if __linux__ +#include +#include +#include +#endif #include #include @@ -110,6 +115,45 @@ bool NetUtilInternal::RetrieveEthernetAddr() { return false; } +const std::string& NetUtilInternal::GetDefaultGateway() const { + return default_gateway; +} + +bool NetUtilInternal::RetrieveDefaultGateway() { + std::scoped_lock lock{m_mutex}; + +#ifdef _WIN32 + +#elif defined(__APPLE__) + +#else + std::ifstream route{"/proc/net/route"}; + std::string line; + + std::getline(route, line); + while(std::getline(route, line)) { + std::istringstream iss{line}; + std::string iface, destination, gateway; + int flags; + + iss >> iface >> destination >> gateway >> std::hex >> flags; + + if (destination == "00000000") { + u64 default_gateway{}; + std::stringstream ss; + ss << std::hex << gateway; + ss >> default_gateway; + + in_addr addr; + addr.s_addr = default_gateway; + this->default_gateway = inet_ntoa(addr); + return true; + } + } +#endif + return false; +} + const std::string& NetUtilInternal::GetNetmask() const { return netmask; } diff --git a/src/core/libraries/network/net_util.h b/src/core/libraries/network/net_util.h index 97f671705..fce55c2ff 100644 --- a/src/core/libraries/network/net_util.h +++ b/src/core/libraries/network/net_util.h @@ -15,13 +15,16 @@ public: private: std::array ether_address{}; + std::string default_gateway{}; std::string netmask{}; std::mutex m_mutex; public: const std::array& GetEthernetAddr() const; + const std::string& GetDefaultGateway() const; const std::string& GetNetmask() const; bool RetrieveEthernetAddr(); + bool RetrieveDefaultGateway(); bool RetrieveNetmask(); }; } // namespace NetUtil \ No newline at end of file diff --git a/src/core/libraries/network/netctl.cpp b/src/core/libraries/network/netctl.cpp index 6c874b400..4ba96fb1a 100644 --- a/src/core/libraries/network/netctl.cpp +++ b/src/core/libraries/network/netctl.cpp @@ -164,13 +164,13 @@ int PS4_SYSV_ABI sceNetCtlGetIfStat() { int PS4_SYSV_ABI sceNetCtlGetInfo(int code, OrbisNetCtlInfo* info) { LOG_DEBUG(Lib_NetCtl, "code = {}", code); + auto* netinfo = Common::Singleton::Instance(); switch (code) { case ORBIS_NET_CTL_INFO_DEVICE: info->device = ORBIS_NET_CTL_DEVICE_WIRED; break; case ORBIS_NET_CTL_INFO_ETHER_ADDR: { - auto* netinfo = Common::Singleton::Instance(); netinfo->RetrieveEthernetAddr(); memcpy(info->ether_addr.data, netinfo->GetEthernetAddr().data(), 6); } break; @@ -221,7 +221,6 @@ int PS4_SYSV_ABI sceNetCtlGetInfo(int code, OrbisNetCtlInfo* info) { // info-> = ; break; case ORBIS_NET_CTL_INFO_NETMASK: { - auto* netinfo = Common::Singleton::Instance(); auto success = netinfo->RetrieveNetmask(); if (success) { strncpy(info->netmask, netinfo->GetNetmask().data(), sizeof(info->netmask)); @@ -231,6 +230,16 @@ int PS4_SYSV_ABI sceNetCtlGetInfo(int code, OrbisNetCtlInfo* info) { } break; } + case ORBIS_NET_CTL_INFO_DEFAULT_ROUTE: { + auto success = netinfo->RetrieveDefaultGateway(); + if (success) { + strncpy(info->netmask, netinfo->GetDefaultGateway().data(), sizeof(info->netmask)); + LOG_DEBUG(Lib_NetCtl, "default gateway: {}", info->netmask); + } else { + LOG_WARNING(Lib_NetCtl, "default gateway: failed to retrieve"); + } + break; + } default: LOG_ERROR(Lib_NetCtl, "{} unsupported code", code); } From 52107fa5ad51d5400a2d0401c07e30c2ee5ebd68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Mon, 14 Jul 2025 20:28:38 +0100 Subject: [PATCH 42/62] Extract EpollTable from net --- CMakeLists.txt | 2 + src/core/libraries/network/net.cpp | 117 +++++------------------ src/core/libraries/network/net_epoll.cpp | 68 +++++++++++++ src/core/libraries/network/net_epoll.h | 61 ++++++++++++ 4 files changed, 154 insertions(+), 94 deletions(-) create mode 100644 src/core/libraries/network/net_epoll.cpp create mode 100644 src/core/libraries/network/net_epoll.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 24a81243f..c180cc061 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -378,6 +378,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 diff --git a/src/core/libraries/network/net.cpp b/src/core/libraries/network/net.cpp index e4f1a8e0d..6d2efef3e 100644 --- a/src/core/libraries/network/net.cpp +++ b/src/core/libraries/network/net.cpp @@ -20,45 +20,15 @@ #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" #include "sockets.h" #include "sys_net.h" -#ifdef __linux__ -#include -#endif namespace Libraries::Net { -struct Epoll { - std::vector> events{}; - const char* name; - int epoll_fd; - - explicit Epoll(const char* name_) : name(name_), epoll_fd(epoll_create1(0)) { - ASSERT(epoll_fd != -1); - } - - bool Destroyed() const noexcept { - return destroyed; - } - - void Destroy() noexcept { - events.clear(); - close(epoll_fd); - epoll_fd = -1; - name = nullptr; - destroyed = true; - } - -private: - bool destroyed{}; -}; - -std::vector epolls; -std::mutex epolls_mutex; - static thread_local int32_t net_errno = 0; static bool g_isNetInitialized = true; // TODO init it properly @@ -705,50 +675,18 @@ int PS4_SYSV_ABI sceNetEpollAbort() { return ORBIS_OK; } -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 PS4_SYSV_ABI sceNetEpollControl(OrbisNetId epollid, OrbisNetEpollFlag op, OrbisNetId id, OrbisNetEpollEvent* event) { LOG_WARNING(Lib_Net, "called, epollid = {}, op = {}, id = {}", epollid, magic_enum::enum_name(op), id); - std::scoped_lock lock{epolls_mutex}; - if (epollid >= epolls.size() || epolls[epollid].Destroyed()) { + auto epoll = Common::Singleton::Instance()->GetEpoll(epollid); + if (!epoll) { return -ORBIS_NET_EBADF; } auto find_id = [&](OrbisNetId id) { - return std::ranges::find_if(epolls[epollid].events, + return std::ranges::find_if(epoll->events, [&](const auto& el) { return el.first == id; }); }; @@ -757,7 +695,7 @@ int PS4_SYSV_ABI sceNetEpollControl(OrbisNetId epollid, OrbisNetEpollFlag op, Or if (event == nullptr) { return -ORBIS_NET_EINVAL; } - if (find_id(id) != epolls[epollid].events.end()) { + if (find_id(id) != epoll->events.end()) { return -ORBIS_NET_EEXIST; } @@ -771,10 +709,11 @@ int PS4_SYSV_ABI sceNetEpollControl(OrbisNetId epollid, OrbisNetEpollFlag op, Or const auto socket = file->socket; epoll_event native_event = {.events = ConvertEpollEventsIn(event->events), .data = {.fd = id}}; - ASSERT(epoll_ctl(epolls[epollid].epoll_fd, EPOLL_CTL_ADD, socket->Native(), + ASSERT(epoll_ctl(epoll->epoll_fd, EPOLL_CTL_ADD, socket->Native(), &native_event) == 0); + LOG_DEBUG(Lib_Net, "epoll_ctl succeeded"); #endif - epolls[epollid].events.emplace_back(id, *event); + epoll->events.emplace_back(id, *event); break; } case ORBIS_NET_EPOLL_CTL_MOD: { @@ -783,7 +722,7 @@ int PS4_SYSV_ABI sceNetEpollControl(OrbisNetId epollid, OrbisNetEpollFlag op, Or } auto it = find_id(id); - if (it == epolls[epollid].events.end()) { + if (it == epoll->events.end()) { return -ORBIS_NET_EEXIST; } @@ -797,15 +736,15 @@ int PS4_SYSV_ABI sceNetEpollControl(OrbisNetId epollid, OrbisNetEpollFlag op, Or } auto it = find_id(id); - if (it == epolls[epollid].events.end()) { + if (it == epoll->events.end()) { return -ORBIS_NET_EBADF; } #ifdef __linux__ const auto socket = Common::Singleton::Instance()->socks[id]; - ASSERT(epoll_ctl(epolls[epollid].epoll_fd, EPOLL_CTL_DEL, socket->Native(), nullptr) == 0); + ASSERT(epoll_ctl(epoll->epoll_fd, EPOLL_CTL_DEL, socket->Native(), nullptr) == 0); #endif - epolls[epollid].events.erase(it); + epoll->events.erase(it); break; } default: @@ -821,30 +760,20 @@ int PS4_SYSV_ABI sceNetEpollCreate(const char* name, int flags) { return -ORBIS_NET_EINVAL; } - std::scoped_lock lock{epolls_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; - } + auto epoll = Common::Singleton::Instance()->CreateHandle(name); + + return epoll; } int PS4_SYSV_ABI sceNetEpollDestroy(OrbisNetId epollid) { LOG_INFO(Lib_Net, "called, epollid = {}", epollid); - std::scoped_lock lock{epolls_mutex}; - if (epollid >= epolls.size() || epolls[epollid].Destroyed()) { + auto epoll = Common::Singleton::Instance()->GetEpoll(epollid); + if (!epoll) { return -ORBIS_NET_EBADF; } - epolls[epollid].Destroy(); + epoll->Destroy(); return ORBIS_OK; } @@ -854,13 +783,13 @@ int PS4_SYSV_ABI sceNetEpollWait(OrbisNetId epollid, OrbisNetEpollEvent* events, LOG_WARNING(Lib_Net, "called, epollid = {}, maxevents = {}, timeout = {}", epollid, maxevents, timeout); - std::scoped_lock lock{epolls_mutex}; - if (epollid >= epolls.size() || epolls[epollid].Destroyed()) { + auto epoll = Common::Singleton::Instance()->GetEpoll(epollid); + if (!epoll) { return -ORBIS_NET_EBADF; } #ifdef __linux__ std::vector native_events{static_cast(maxevents)}; - int result = epoll_wait(epolls[epollid].epoll_fd, native_events.data(), maxevents, + int result = epoll_wait(epoll->epoll_fd, native_events.data(), maxevents, timeout == -1 ? timeout : timeout / 1000); if (result < 0) { LOG_ERROR(Lib_Net, "epoll_wait failed with {}", Common::GetLastErrorMsg()); @@ -873,10 +802,10 @@ int PS4_SYSV_ABI sceNetEpollWait(OrbisNetId epollid, OrbisNetEpollEvent* events, const auto& current_event = native_events[i]; LOG_INFO(Lib_Net, "native_event[{}] = ( .events = {}, .data = {:#x} )", i, current_event.events, current_event.data.u64); - const auto it = std::ranges::find_if(epolls[epollid].events, [&](auto& el) { + const auto it = std::ranges::find_if(epoll->events, [&](auto& el) { return el.first == current_event.data.fd; }); - ASSERT(it != epolls[epollid].events.end()); + ASSERT(it != epoll->events.end()); events[i] = { .events = ConvertEpollEventsOut(current_event.events), .ident = static_cast(current_event.data.fd), diff --git a/src/core/libraries/network/net_epoll.cpp b/src/core/libraries/network/net_epoll.cpp new file mode 100644 index 000000000..1c7bf3dbb --- /dev/null +++ b/src/core/libraries/network/net_epoll.cpp @@ -0,0 +1,68 @@ +// 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 d) { + UNREACHABLE(); +} + +} // 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..c34e2d4b6 --- /dev/null +++ b/src/core/libraries/network/net_epoll.h @@ -0,0 +1,61 @@ +// 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 +#include + +#ifdef __linux__ +#include +#endif + +namespace Libraries::Net { + +struct Epoll { + std::vector> events{}; + const char* name; + int epoll_fd; + + explicit Epoll(const char* name_) : name(name_), epoll_fd(epoll_create1(0)) { + ASSERT(epoll_fd != -1); + } + + bool Destroyed() const noexcept { + return destroyed; + } + + void Destroy() noexcept { + events.clear(); + close(epoll_fd); + epoll_fd = -1; + name = nullptr; + 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 From 63532b623f0107c087a13e2b7ce61a4b237601cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Mon, 14 Jul 2025 20:29:57 +0100 Subject: [PATCH 43/62] Return positive net resolver id --- src/core/libraries/network/net.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/libraries/network/net.cpp b/src/core/libraries/network/net.cpp index 6d2efef3e..c560fc214 100644 --- a/src/core/libraries/network/net.cpp +++ b/src/core/libraries/network/net.cpp @@ -1557,7 +1557,8 @@ int PS4_SYSV_ABI sceNetResolverConnectDestroy() { int PS4_SYSV_ABI sceNetResolverCreate(const char* name, int poolid, int flags) { LOG_ERROR(Lib_Net, "(STUBBED) called, name = {}, poolid = {}, flags = {}", name, poolid, flags); - return ORBIS_OK; + static int id = 1; + return id++; } int PS4_SYSV_ABI sceNetResolverDestroy(OrbisNetId resolverid) { From 840baac1e1ab36bd634dfe1119a9918aa8a6ace4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Mon, 14 Jul 2025 20:32:35 +0100 Subject: [PATCH 44/62] clang-format --- src/core/libraries/network/net.cpp | 11 ++++------- src/core/libraries/network/net_epoll.cpp | 1 - src/core/libraries/network/net_epoll.h | 2 +- src/core/libraries/network/net_util.cpp | 16 ++++++++-------- 4 files changed, 13 insertions(+), 17 deletions(-) diff --git a/src/core/libraries/network/net.cpp b/src/core/libraries/network/net.cpp index c560fc214..b3837f317 100644 --- a/src/core/libraries/network/net.cpp +++ b/src/core/libraries/network/net.cpp @@ -686,8 +686,7 @@ int PS4_SYSV_ABI sceNetEpollControl(OrbisNetId epollid, OrbisNetEpollFlag op, Or } auto find_id = [&](OrbisNetId id) { - return std::ranges::find_if(epoll->events, - [&](const auto& el) { return el.first == id; }); + return std::ranges::find_if(epoll->events, [&](const auto& el) { return el.first == id; }); }; switch (op) { @@ -709,8 +708,7 @@ int PS4_SYSV_ABI sceNetEpollControl(OrbisNetId epollid, OrbisNetEpollFlag op, Or const auto socket = file->socket; epoll_event native_event = {.events = ConvertEpollEventsIn(event->events), .data = {.fd = id}}; - ASSERT(epoll_ctl(epoll->epoll_fd, EPOLL_CTL_ADD, socket->Native(), - &native_event) == 0); + ASSERT(epoll_ctl(epoll->epoll_fd, EPOLL_CTL_ADD, socket->Native(), &native_event) == 0); LOG_DEBUG(Lib_Net, "epoll_ctl succeeded"); #endif epoll->events.emplace_back(id, *event); @@ -802,9 +800,8 @@ int PS4_SYSV_ABI sceNetEpollWait(OrbisNetId epollid, OrbisNetEpollEvent* events, const auto& current_event = native_events[i]; LOG_INFO(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; - }); + 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), diff --git a/src/core/libraries/network/net_epoll.cpp b/src/core/libraries/network/net_epoll.cpp index 1c7bf3dbb..5a1d34fe8 100644 --- a/src/core/libraries/network/net_epoll.cpp +++ b/src/core/libraries/network/net_epoll.cpp @@ -58,7 +58,6 @@ int EpollTable::CreateHandle(const char* name) { void EpollTable::DeleteHandle(int d) { UNREACHABLE(); - } Epoll* EpollTable::GetEpoll(int d) { diff --git a/src/core/libraries/network/net_epoll.h b/src/core/libraries/network/net_epoll.h index c34e2d4b6..5363efff0 100644 --- a/src/core/libraries/network/net_epoll.h +++ b/src/core/libraries/network/net_epoll.h @@ -5,6 +5,7 @@ #include "common/types.h" #include "core/libraries/network/net.h" + #include #include #include @@ -40,7 +41,6 @@ private: bool destroyed{}; }; - u32 ConvertEpollEventsIn(u32 orbis_events); u32 ConvertEpollEventsOut(u32 epoll_events); diff --git a/src/core/libraries/network/net_util.cpp b/src/core/libraries/network/net_util.cpp index aaedcc12a..457ceef91 100644 --- a/src/core/libraries/network/net_util.cpp +++ b/src/core/libraries/network/net_util.cpp @@ -25,8 +25,8 @@ typedef int net_socket; #include #endif #if __linux__ -#include #include +#include #include #endif @@ -131,7 +131,7 @@ bool NetUtilInternal::RetrieveDefaultGateway() { std::string line; std::getline(route, line); - while(std::getline(route, line)) { + while (std::getline(route, line)) { std::istringstream iss{line}; std::string iface, destination, gateway; int flags; @@ -167,12 +167,13 @@ bool NetUtilInternal::RetrieveNetmask() { std::vector adapter_addresses(sizeof(IP_ADAPTER_ADDRESSES)); ULONG size_infos = sizeof(IP_ADAPTER_ADDRESSES); - if (GetAdaptersInfo(reinterpret_cast(adapter_infos.data()), &size_infos) == - ERROR_BUFFER_OVERFLOW) + if (GetAdaptersInfo(reinterpret_cast(adapter_infos.data()), + &size_infos) == ERROR_BUFFER_OVERFLOW) adapter_infos.resize(size_infos); - if (GetAdaptersInfo(reinterpret_cast(adapter_infos.data()), &size_infos) == - NO_ERROR && size_infos) { + if (GetAdaptersInfo(reinterpret_cast(adapter_infos.data()), + &size_infos) == NO_ERROR && + size_infos) { PIP_ADAPTER_ADDRESSES adapter; for (adapter = adapter_addresses; adapter; adapter = adapter->Next) { PIP_ADAPTER_UNICAST_ADDRESS unicast = adapter->FirstUnicastAddress; @@ -203,12 +204,11 @@ bool NetUtilInternal::RetrieveNetmask() { freeifaddrs(ifap); #endif - + if (success) { netmask = netmaskStr; } return success; } - } // namespace NetUtil \ No newline at end of file From caa38af40b06cbe279bf0040f4b15e1e0bddfa42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Mon, 14 Jul 2025 20:48:21 +0100 Subject: [PATCH 45/62] Include wepoll library --- .gitmodules | 3 +++ externals/wepoll | 1 + src/core/libraries/network/net_epoll.h | 15 +++++++++++++-- 3 files changed, 17 insertions(+), 2 deletions(-) create mode 160000 externals/wepoll diff --git a/.gitmodules b/.gitmodules index 25b5d307b..6be16956c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -106,3 +106,6 @@ [submodule "externals/libusb"] path = externals/libusb url = https://github.com/libusb/libusb-cmake.git +[submodule "externals/wepoll"] + path = externals/wepoll + url = https://github.com/piscisaureus/wepoll.git diff --git a/externals/wepoll b/externals/wepoll new file mode 160000 index 000000000..0598a791b --- /dev/null +++ b/externals/wepoll @@ -0,0 +1 @@ +Subproject commit 0598a791bf9cbbf480793d778930fc635b044980 diff --git a/src/core/libraries/network/net_epoll.h b/src/core/libraries/network/net_epoll.h index 5363efff0..bd2117058 100644 --- a/src/core/libraries/network/net_epoll.h +++ b/src/core/libraries/network/net_epoll.h @@ -10,16 +10,27 @@ #include #include +#ifdef _WIN32 +#include +#endif + #ifdef __linux__ #include +#define epoll_close close #endif namespace Libraries::Net { +#ifdef _WIN32 +using epoll_handle = HANDLE; +#elif defined(__linux__) +using epoll_handle = int; +#endif + struct Epoll { std::vector> events{}; const char* name; - int epoll_fd; + epoll_handle epoll_fd; explicit Epoll(const char* name_) : name(name_), epoll_fd(epoll_create1(0)) { ASSERT(epoll_fd != -1); @@ -31,7 +42,7 @@ struct Epoll { void Destroy() noexcept { events.clear(); - close(epoll_fd); + epoll_close(epoll_fd); epoll_fd = -1; name = nullptr; destroyed = true; From c8885471f4e37a87731d4c066ac3ebae9d222eb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Mon, 14 Jul 2025 21:00:03 +0100 Subject: [PATCH 46/62] Include epoll-shim library --- .gitmodules | 3 +++ CMakeLists.txt | 3 ++- externals/epoll-shim | 1 + src/core/libraries/network/net_epoll.h | 9 ++++++--- 4 files changed, 12 insertions(+), 4 deletions(-) create mode 160000 externals/epoll-shim diff --git a/.gitmodules b/.gitmodules index 6be16956c..a3798e704 100644 --- a/.gitmodules +++ b/.gitmodules @@ -109,3 +109,6 @@ [submodule "externals/wepoll"] path = externals/wepoll url = https://github.com/piscisaureus/wepoll.git +[submodule "externals/epoll-shim"] + path = externals/epoll-shim + url = https://github.com/jiixyj/epoll-shim.git diff --git a/CMakeLists.txt b/CMakeLists.txt index c180cc061..877a9c6da 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -246,6 +246,7 @@ find_package(pugixml 1.14 CONFIG) find_package(libusb 1.0.27 MODULE) if (APPLE) find_package(date 3.0.1 CONFIG) + find_package(epoll-shim 3.14 CONFIG) endif() list(POP_BACK CMAKE_MODULE_PATH) @@ -1175,7 +1176,7 @@ if (APPLE) endif() # Replacement for std::chrono::time_zone - target_link_libraries(shadps4 PRIVATE date::date-tz) + target_link_libraries(shadps4 PRIVATE date::date-tz epoll-shim) endif() if (ENABLE_QT_GUI) diff --git a/externals/epoll-shim b/externals/epoll-shim new file mode 160000 index 000000000..18159584b --- /dev/null +++ b/externals/epoll-shim @@ -0,0 +1 @@ +Subproject commit 18159584bb3d17e601b9315a7398ace018251bdc diff --git a/src/core/libraries/network/net_epoll.h b/src/core/libraries/network/net_epoll.h index bd2117058..fdf2f00fb 100644 --- a/src/core/libraries/network/net_epoll.h +++ b/src/core/libraries/network/net_epoll.h @@ -14,16 +14,15 @@ #include #endif -#ifdef __linux__ +#if defined(__linux__) || defined(__APPLE__) #include -#define epoll_close close #endif namespace Libraries::Net { #ifdef _WIN32 using epoll_handle = HANDLE; -#elif defined(__linux__) +#else using epoll_handle = int; #endif @@ -42,7 +41,11 @@ struct Epoll { void Destroy() noexcept { events.clear(); + #ifdef _WIN32 epoll_close(epoll_fd); + #else + close(epoll_fd); + #endif epoll_fd = -1; name = nullptr; destroyed = true; From b852b1834dc63d4c0b41c233aed4c87f286d42da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Mon, 14 Jul 2025 21:02:22 +0100 Subject: [PATCH 47/62] clang-format --- src/core/libraries/network/net_epoll.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/libraries/network/net_epoll.h b/src/core/libraries/network/net_epoll.h index fdf2f00fb..6abb5dccb 100644 --- a/src/core/libraries/network/net_epoll.h +++ b/src/core/libraries/network/net_epoll.h @@ -41,11 +41,11 @@ struct Epoll { void Destroy() noexcept { events.clear(); - #ifdef _WIN32 +#ifdef _WIN32 epoll_close(epoll_fd); - #else +#else close(epoll_fd); - #endif +#endif epoll_fd = -1; name = nullptr; destroyed = true; From dc3bd1e5d455d49d40d2454dcf7244f6ff131119 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Mon, 14 Jul 2025 21:28:11 +0100 Subject: [PATCH 48/62] Extract socket write to a method in Socket --- src/core/libraries/kernel/file_system.cpp | 2 +- src/core/libraries/network/p2p_sockets.cpp | 5 +++++ src/core/libraries/network/posix_sockets.cpp | 9 +++++++++ src/core/libraries/network/sockets.h | 3 +++ 4 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/core/libraries/kernel/file_system.cpp b/src/core/libraries/kernel/file_system.cpp index 4a6938b10..bccffbc6c 100644 --- a/src/core/libraries/kernel/file_system.cpp +++ b/src/core/libraries/kernel/file_system.cpp @@ -304,7 +304,7 @@ s64 PS4_SYSV_ABI write(s32 fd, const void* buf, size_t nbytes) { } return result; } else if (file->type == Core::FileSys::FileType::Socket) { - s64 result = ::write(file->socket->Native(), buf, nbytes); + s64 result = file->socket->write(buf, nbytes); if (result < 0) { ErrSceToPosix(result); return -1; diff --git a/src/core/libraries/network/p2p_sockets.cpp b/src/core/libraries/network/p2p_sockets.cpp index 796a4c562..42e3ac92c 100644 --- a/src/core/libraries/network/p2p_sockets.cpp +++ b/src/core/libraries/network/p2p_sockets.cpp @@ -62,4 +62,9 @@ int P2PSocket::GetPeerName(OrbisNetSockaddr* addr, u32* namelen) { return 0; } +int P2PSocket::write(const void* buf, size_t len) { + LOG_ERROR(Lib_Net, "(STUBBED) called"); + return 0; +} + } // 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 eddf1f2f9..9b83058d5 100644 --- a/src/core/libraries/network/posix_sockets.cpp +++ b/src/core/libraries/network/posix_sockets.cpp @@ -458,4 +458,13 @@ int PosixSocket::GetSocketOptions(int level, int optname, void* optval, u32* opt return 0; } +int PosixSocket::write(const void* buf, size_t len) { +#ifdef _WIN32 + return send(sock, buf, len, 0); +#else + return ::write(sock, buf, len); +#endif +} + + } // namespace Libraries::Net \ No newline at end of file diff --git a/src/core/libraries/network/sockets.h b/src/core/libraries/network/sockets.h index ce54ee765..654fd4955 100644 --- a/src/core/libraries/network/sockets.h +++ b/src/core/libraries/network/sockets.h @@ -52,6 +52,7 @@ struct Socket { virtual int Connect(const OrbisNetSockaddr* addr, u32 namelen) = 0; virtual int GetSocketAddress(OrbisNetSockaddr* name, u32* namelen) = 0; virtual int GetPeerName(OrbisNetSockaddr* addr, u32* namelen) = 0; + virtual int write(const void* buf, size_t len) = 0; virtual bool IsValid() const = 0; virtual net_socket Native() const = 0; std::mutex m_mutex; @@ -82,6 +83,7 @@ struct PosixSocket : public Socket { int Connect(const OrbisNetSockaddr* addr, u32 namelen) override; int GetSocketAddress(OrbisNetSockaddr* name, u32* namelen) override; int GetPeerName(OrbisNetSockaddr* addr, u32* namelen) override; + int write(const void* buf, size_t len) override; bool IsValid() const override { return sock != -1; } @@ -104,6 +106,7 @@ struct P2PSocket : public Socket { int Connect(const OrbisNetSockaddr* addr, u32 namelen) override; int GetSocketAddress(OrbisNetSockaddr* name, u32* namelen) override; int GetPeerName(OrbisNetSockaddr* addr, u32* namelen) override; + int write(const void* buf, size_t len) override; bool IsValid() const override { return true; } From ff4570f1cfc965525c076ebdcfa0184e35f0ea83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Mon, 14 Jul 2025 21:30:11 +0100 Subject: [PATCH 49/62] Fix epoll-shim? --- externals/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index 89b0fbfdd..7dfa67bde 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt @@ -229,4 +229,8 @@ if (APPLE) if (NOT TARGET MoltenVK) add_subdirectory(MoltenVK) endif() + + if (NOT TARGET epoll-shim) + add_subdirectory(epoll-shim) + endif() endif() From aa684452ebe265187773ec97d0b81c4a3c79e0c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Mon, 14 Jul 2025 21:35:37 +0100 Subject: [PATCH 50/62] Actually implement EpollTable::GetEpoll --- src/core/libraries/network/net_epoll.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/core/libraries/network/net_epoll.cpp b/src/core/libraries/network/net_epoll.cpp index 5a1d34fe8..e64c8ac64 100644 --- a/src/core/libraries/network/net_epoll.cpp +++ b/src/core/libraries/network/net_epoll.cpp @@ -60,8 +60,13 @@ void EpollTable::DeleteHandle(int d) { UNREACHABLE(); } -Epoll* EpollTable::GetEpoll(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 From 4d6263f368e6b23bdc15261eaa682724d38a9cbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Mon, 14 Jul 2025 21:52:31 +0100 Subject: [PATCH 51/62] Extract socket read to a method in Socket --- src/core/libraries/kernel/file_system.cpp | 2 +- src/core/libraries/network/p2p_sockets.cpp | 5 +++++ src/core/libraries/network/posix_sockets.cpp | 8 ++++++++ src/core/libraries/network/sockets.h | 3 +++ 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/core/libraries/kernel/file_system.cpp b/src/core/libraries/kernel/file_system.cpp index bccffbc6c..87bf71def 100644 --- a/src/core/libraries/kernel/file_system.cpp +++ b/src/core/libraries/kernel/file_system.cpp @@ -492,7 +492,7 @@ s64 PS4_SYSV_ABI read(s32 fd, void* buf, size_t nbytes) { } return result; } else if (file->type == Core::FileSys::FileType::Socket) { - s64 result = ::read(file->socket->Native(), buf, nbytes); + s64 result = file->socket->read(buf, nbytes); if (result < 0) { ErrSceToPosix(result); return -1; diff --git a/src/core/libraries/network/p2p_sockets.cpp b/src/core/libraries/network/p2p_sockets.cpp index 42e3ac92c..dc6eaed57 100644 --- a/src/core/libraries/network/p2p_sockets.cpp +++ b/src/core/libraries/network/p2p_sockets.cpp @@ -62,6 +62,11 @@ int P2PSocket::GetPeerName(OrbisNetSockaddr* addr, u32* namelen) { return 0; } +int P2PSocket::read(void* buf, size_t len) { + LOG_ERROR(Lib_Net, "(STUBBED) called"); + return 0; +} + int P2PSocket::write(const void* buf, size_t len) { LOG_ERROR(Lib_Net, "(STUBBED) called"); return 0; diff --git a/src/core/libraries/network/posix_sockets.cpp b/src/core/libraries/network/posix_sockets.cpp index 9b83058d5..273639396 100644 --- a/src/core/libraries/network/posix_sockets.cpp +++ b/src/core/libraries/network/posix_sockets.cpp @@ -458,6 +458,14 @@ int PosixSocket::GetSocketOptions(int level, int optname, void* optval, u32* opt return 0; } +int PosixSocket::read(void* buf, size_t len) { +#ifdef _WIN32 + return recv(sock, buf, len, 0); +#else + return ::read(sock, buf, len); +#endif +} + int PosixSocket::write(const void* buf, size_t len) { #ifdef _WIN32 return send(sock, buf, len, 0); diff --git a/src/core/libraries/network/sockets.h b/src/core/libraries/network/sockets.h index 654fd4955..0504d6230 100644 --- a/src/core/libraries/network/sockets.h +++ b/src/core/libraries/network/sockets.h @@ -52,6 +52,7 @@ struct Socket { virtual int Connect(const OrbisNetSockaddr* addr, u32 namelen) = 0; virtual int GetSocketAddress(OrbisNetSockaddr* name, u32* namelen) = 0; virtual int GetPeerName(OrbisNetSockaddr* addr, u32* namelen) = 0; + virtual int read(void* buf, size_t len) = 0; virtual int write(const void* buf, size_t len) = 0; virtual bool IsValid() const = 0; virtual net_socket Native() const = 0; @@ -83,6 +84,7 @@ struct PosixSocket : public Socket { int Connect(const OrbisNetSockaddr* addr, u32 namelen) override; int GetSocketAddress(OrbisNetSockaddr* name, u32* namelen) override; int GetPeerName(OrbisNetSockaddr* addr, u32* namelen) override; + int read(void* buf, size_t len) override; int write(const void* buf, size_t len) override; bool IsValid() const override { return sock != -1; @@ -106,6 +108,7 @@ struct P2PSocket : public Socket { int Connect(const OrbisNetSockaddr* addr, u32 namelen) override; int GetSocketAddress(OrbisNetSockaddr* name, u32* namelen) override; int GetPeerName(OrbisNetSockaddr* addr, u32* namelen) override; + int read(void* buf, size_t len) override; int write(const void* buf, size_t len) override; bool IsValid() const override { return true; From 0787dc3e89b034cc83a481ed7cd8a5be2929ac48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Mon, 14 Jul 2025 22:21:06 +0100 Subject: [PATCH 52/62] Extract socket fstat to a method in Socket --- src/core/libraries/kernel/file_system.cpp | 21 +++++++------------- src/core/libraries/network/posix_sockets.cpp | 21 ++++++++++++++++++++ src/core/libraries/network/sockets.h | 7 +++++++ 3 files changed, 35 insertions(+), 14 deletions(-) diff --git a/src/core/libraries/kernel/file_system.cpp b/src/core/libraries/kernel/file_system.cpp index 87bf71def..a96b0b8f7 100644 --- a/src/core/libraries/kernel/file_system.cpp +++ b/src/core/libraries/kernel/file_system.cpp @@ -28,7 +28,6 @@ #else #include #endif -#include namespace D = Core::Devices; using FactoryDevice = std::function(u32, const char*, int, u16)>; @@ -691,18 +690,12 @@ s32 PS4_SYSV_ABI fstat(s32 fd, OrbisKernelStat* sb) { break; } case Core::FileSys::FileType::Socket: { - struct stat st{}; - s32 result = ::fstat(file->socket->Native(), &st); + s32 result = file->socket->fstat(sb); if (result < 0) { ErrSceToPosix(result); return -1; } - sb->st_mode = 0000777u | 0140000u; - sb->st_size = st.st_size; - sb->st_blocks = st.st_blocks; - sb->st_blksize = st.st_blksize; - // sb->st_flags = st.st_flags; - break; + return result; } default: UNREACHABLE(); @@ -1106,10 +1099,10 @@ s32 PS4_SYSV_ABI posix_select(int nfds, fd_set* readfds, fd_set* writefds, fd_se FD_ZERO(&read_host); FD_ZERO(&write_host); FD_ZERO(&except_host); - std::map host_to_guest; + std::map host_to_guest; auto* h = Common::Singleton::Instance(); - int max_fd = 0; + u64 max_fd = 0; for (auto i = 0; i < nfds; ++i) { auto read = readfds && FD_ISSET(i, readfds); @@ -1126,12 +1119,12 @@ s32 PS4_SYSV_ABI posix_select(int nfds, fd_set* readfds, fd_set* writefds, fd_se return -1; } - int fd = [&] { + u64 fd = [&] { switch (file->type) { case Core::FileSys::FileType::Regular: - return static_cast(file->f.GetFileMapping()); + return static_cast(file->f.GetFileMapping()); case Core::FileSys::FileType::Socket: - return file->socket->Native(); + return static_cast(file->socket->Native()); default: UNREACHABLE(); } diff --git a/src/core/libraries/network/posix_sockets.cpp b/src/core/libraries/network/posix_sockets.cpp index 273639396..ed42ae0a5 100644 --- a/src/core/libraries/network/posix_sockets.cpp +++ b/src/core/libraries/network/posix_sockets.cpp @@ -3,7 +3,11 @@ #include #include "common/error.h" +#include "core/libraries/kernel/file_system.h" #include "net.h" +#ifndef _WIN32 +#include +#endif #include "net_error.h" #include "sockets.h" @@ -458,6 +462,23 @@ int PosixSocket::GetSocketOptions(int level, int optname, void* optval, u32* opt return 0; } +int PosixSocket::fstat(Libraries::Kernel::OrbisKernelStat* sb) { +#ifdef _WIN32 + LOG_ERROR(Lib_Net, "(STUBBED) called"); + sb->st_mode = 0000777u | 0140000u; + return 0; +#else + struct stat st{}; + int result = ::fstat(sock, &st); + sb->st_mode = 0000777u | 0140000u; + sb->st_size = st.st_size; + sb->st_blocks = st.st_blocks; + sb->st_blksize = st.st_blksize; + // sb->st_flags = st.st_flags; + return result; +#endif +} + int PosixSocket::read(void* buf, size_t len) { #ifdef _WIN32 return recv(sock, buf, len, 0); diff --git a/src/core/libraries/network/sockets.h b/src/core/libraries/network/sockets.h index 0504d6230..53d7cd98a 100644 --- a/src/core/libraries/network/sockets.h +++ b/src/core/libraries/network/sockets.h @@ -26,6 +26,10 @@ typedef int net_socket; #include #include "net.h" +namespace Libraries::Kernel { +struct OrbisKernelStat; +} + namespace Libraries::Net { struct Socket; @@ -52,6 +56,7 @@ struct Socket { virtual int Connect(const OrbisNetSockaddr* addr, u32 namelen) = 0; virtual int GetSocketAddress(OrbisNetSockaddr* name, u32* namelen) = 0; virtual int GetPeerName(OrbisNetSockaddr* addr, u32* namelen) = 0; + virtual int fstat(Libraries::Kernel::OrbisKernelStat* stat) = 0; virtual int read(void* buf, size_t len) = 0; virtual int write(const void* buf, size_t len) = 0; virtual bool IsValid() const = 0; @@ -84,6 +89,7 @@ struct PosixSocket : public Socket { int Connect(const OrbisNetSockaddr* addr, u32 namelen) override; int GetSocketAddress(OrbisNetSockaddr* name, u32* namelen) override; int GetPeerName(OrbisNetSockaddr* addr, u32* namelen) override; + int fstat(Libraries::Kernel::OrbisKernelStat* stat) override; int read(void* buf, size_t len) override; int write(const void* buf, size_t len) override; bool IsValid() const override { @@ -110,6 +116,7 @@ struct P2PSocket : public Socket { int GetPeerName(OrbisNetSockaddr* addr, u32* namelen) override; int read(void* buf, size_t len) override; int write(const void* buf, size_t len) override; + int fstat(Libraries::Kernel::OrbisKernelStat* stat) override; bool IsValid() const override { return true; } From 322fcf7e650e2c57b2c6d857d9a6d7e2170cf1d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Mon, 14 Jul 2025 22:22:03 +0100 Subject: [PATCH 53/62] _WIN32 --- src/core/libraries/kernel/threads/pthread.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/libraries/kernel/threads/pthread.cpp b/src/core/libraries/kernel/threads/pthread.cpp index e1c22bc55..0855c804e 100644 --- a/src/core/libraries/kernel/threads/pthread.cpp +++ b/src/core/libraries/kernel/threads/pthread.cpp @@ -337,7 +337,7 @@ void PS4_SYSV_ABI sched_yield() { } int PS4_SYSV_ABI posix_getpid() { -#ifdef WIN32 +#ifdef _WIN32 return GetCurrentProcessId(); #else return getpid(); From 73d76bd57a2c837b88a58fdcbabbdefef0e683fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Mon, 14 Jul 2025 22:33:07 +0100 Subject: [PATCH 54/62] fix --- src/core/libraries/network/net_epoll.h | 2 +- src/core/libraries/network/net_util.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/libraries/network/net_epoll.h b/src/core/libraries/network/net_epoll.h index 6abb5dccb..6bdbe4814 100644 --- a/src/core/libraries/network/net_epoll.h +++ b/src/core/libraries/network/net_epoll.h @@ -8,7 +8,6 @@ #include #include -#include #ifdef _WIN32 #include @@ -16,6 +15,7 @@ #if defined(__linux__) || defined(__APPLE__) #include +#include #endif namespace Libraries::Net { diff --git a/src/core/libraries/network/net_util.cpp b/src/core/libraries/network/net_util.cpp index 457ceef91..826540cb2 100644 --- a/src/core/libraries/network/net_util.cpp +++ b/src/core/libraries/network/net_util.cpp @@ -167,11 +167,11 @@ bool NetUtilInternal::RetrieveNetmask() { std::vector adapter_addresses(sizeof(IP_ADAPTER_ADDRESSES)); ULONG size_infos = sizeof(IP_ADAPTER_ADDRESSES); - if (GetAdaptersInfo(reinterpret_cast(adapter_infos.data()), + if (GetAdaptersInfo(reinterpret_cast(adapter_addresses.data()), &size_infos) == ERROR_BUFFER_OVERFLOW) - adapter_infos.resize(size_infos); + adapter_addresses.resize(size_infos); - if (GetAdaptersInfo(reinterpret_cast(adapter_infos.data()), + if (GetAdaptersInfo(reinterpret_cast(adapter_addresses.data()), &size_infos) == NO_ERROR && size_infos) { PIP_ADAPTER_ADDRESSES adapter; From 262be4a358a40ed46ee00e8f2ed7a0619a2e5d9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Mon, 14 Jul 2025 22:47:36 +0100 Subject: [PATCH 55/62] fix2 --- externals/CMakeLists.txt | 2 ++ src/core/libraries/network/net_epoll.h | 2 +- src/core/libraries/network/net_util.cpp | 6 +++--- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index 7dfa67bde..4d7e3db04 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt @@ -140,6 +140,8 @@ endif() # sirit add_subdirectory(sirit) if (WIN32) + add_library(wepoll wepoll/wepoll.c) + target_include_directories(wepoll INTERFACE wepoll/) target_compile_options(sirit PUBLIC "-Wno-error=unused-command-line-argument") endif() diff --git a/src/core/libraries/network/net_epoll.h b/src/core/libraries/network/net_epoll.h index 6bdbe4814..c32db254b 100644 --- a/src/core/libraries/network/net_epoll.h +++ b/src/core/libraries/network/net_epoll.h @@ -10,7 +10,7 @@ #include #ifdef _WIN32 -#include +#include #endif #if defined(__linux__) || defined(__APPLE__) diff --git a/src/core/libraries/network/net_util.cpp b/src/core/libraries/network/net_util.cpp index 826540cb2..a765724f3 100644 --- a/src/core/libraries/network/net_util.cpp +++ b/src/core/libraries/network/net_util.cpp @@ -167,15 +167,15 @@ bool NetUtilInternal::RetrieveNetmask() { std::vector adapter_addresses(sizeof(IP_ADAPTER_ADDRESSES)); ULONG size_infos = sizeof(IP_ADAPTER_ADDRESSES); - if (GetAdaptersInfo(reinterpret_cast(adapter_addresses.data()), + if (GetAdaptersAddresses(AF_INET, 0, NULL, reinterpret_cast(adapter_addresses.data()), &size_infos) == ERROR_BUFFER_OVERFLOW) adapter_addresses.resize(size_infos); - if (GetAdaptersInfo(reinterpret_cast(adapter_addresses.data()), + if (GetAdaptersAddresses(AF_INET, 0, NULL, reinterpret_cast(adapter_addresses.data()), &size_infos) == NO_ERROR && size_infos) { PIP_ADAPTER_ADDRESSES adapter; - for (adapter = adapter_addresses; adapter; adapter = adapter->Next) { + for (adapter = reinterpret_cast(adapter_addresses.data()); adapter; adapter = adapter->Next) { PIP_ADAPTER_UNICAST_ADDRESS unicast = adapter->FirstUnicastAddress; if (unicast) { ULONG prefix_length = unicast->OnLinkPrefixLength; From f82c5a221e4190886256fe3c6becf55dc56f7678 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Tue, 15 Jul 2025 16:52:40 +0200 Subject: [PATCH 56/62] Update src/core/libraries/network/p2p_sockets.cpp Co-authored-by: kalaposfos13 <153381648+kalaposfos13@users.noreply.github.com> --- src/core/libraries/network/p2p_sockets.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/core/libraries/network/p2p_sockets.cpp b/src/core/libraries/network/p2p_sockets.cpp index dc6eaed57..32b4b9f7a 100644 --- a/src/core/libraries/network/p2p_sockets.cpp +++ b/src/core/libraries/network/p2p_sockets.cpp @@ -72,4 +72,8 @@ int P2PSocket::write(const void* buf, size_t len) { return 0; } +int P2PSocket::fstat(Libraries::Kernel::OrbisKernelStat* stat) { + LOG_ERROR(Lib_Net, "(STUBBED) called"); + return 0; +} } // namespace Libraries::Net \ No newline at end of file From adb86b64d32d5906bea9e90730b64ff792832696 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Tue, 15 Jul 2025 18:13:02 +0100 Subject: [PATCH 57/62] clang-format --- src/core/libraries/network/net_util.cpp | 13 ++++++++----- src/core/libraries/network/posix_sockets.cpp | 1 - 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/core/libraries/network/net_util.cpp b/src/core/libraries/network/net_util.cpp index a765724f3..3e6aa9eeb 100644 --- a/src/core/libraries/network/net_util.cpp +++ b/src/core/libraries/network/net_util.cpp @@ -167,15 +167,18 @@ bool NetUtilInternal::RetrieveNetmask() { std::vector adapter_addresses(sizeof(IP_ADAPTER_ADDRESSES)); ULONG size_infos = sizeof(IP_ADAPTER_ADDRESSES); - if (GetAdaptersAddresses(AF_INET, 0, NULL, reinterpret_cast(adapter_addresses.data()), - &size_infos) == ERROR_BUFFER_OVERFLOW) + if (GetAdaptersAddresses(AF_INET, 0, NULL, + reinterpret_cast(adapter_addresses.data()), + &size_infos) == ERROR_BUFFER_OVERFLOW) adapter_addresses.resize(size_infos); - if (GetAdaptersAddresses(AF_INET, 0, NULL, reinterpret_cast(adapter_addresses.data()), - &size_infos) == NO_ERROR && + if (GetAdaptersAddresses(AF_INET, 0, NULL, + reinterpret_cast(adapter_addresses.data()), + &size_infos) == NO_ERROR && size_infos) { PIP_ADAPTER_ADDRESSES adapter; - for (adapter = reinterpret_cast(adapter_addresses.data()); adapter; adapter = adapter->Next) { + for (adapter = reinterpret_cast(adapter_addresses.data()); adapter; + adapter = adapter->Next) { PIP_ADAPTER_UNICAST_ADDRESS unicast = adapter->FirstUnicastAddress; if (unicast) { ULONG prefix_length = unicast->OnLinkPrefixLength; diff --git a/src/core/libraries/network/posix_sockets.cpp b/src/core/libraries/network/posix_sockets.cpp index ed42ae0a5..330f4f4f2 100644 --- a/src/core/libraries/network/posix_sockets.cpp +++ b/src/core/libraries/network/posix_sockets.cpp @@ -495,5 +495,4 @@ int PosixSocket::write(const void* buf, size_t len) { #endif } - } // namespace Libraries::Net \ No newline at end of file From 36c0267e145e5aaeb60108e2d4e6b6cb14601603 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Tue, 15 Jul 2025 18:54:59 +0100 Subject: [PATCH 58/62] Steal and improve shadow's select for Windows --- src/core/libraries/kernel/file_system.cpp | 159 ++++++++++++++++++++-- 1 file changed, 150 insertions(+), 9 deletions(-) diff --git a/src/core/libraries/kernel/file_system.cpp b/src/core/libraries/kernel/file_system.cpp index a96b0b8f7..d71219c71 100644 --- a/src/core/libraries/kernel/file_system.cpp +++ b/src/core/libraries/kernel/file_system.cpp @@ -24,6 +24,7 @@ #include "kernel.h" #ifdef _WIN32 +#include #include #else #include @@ -1087,22 +1088,161 @@ s32 PS4_SYSV_ABI sceKernelUnlink(const char* path) { s32 PS4_SYSV_ABI posix_select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, OrbisKernelTimeval* timeout) { - LOG_ERROR(Kernel_Fs, - "(STUBBED) nfds = {}, readfds = {:#x}, writefds = {:#x}, exceptfds = {:#x}, timeout " + LOG_INFO(Kernel_Fs, + "nfds = {}, readfds = {:#x}, writefds = {:#x}, exceptfds = {:#x}, timeout " "= {:#x}", nfds, reinterpret_cast(readfds), reinterpret_cast(writefds), reinterpret_cast(exceptfds), reinterpret_cast(timeout)); - LOG_INFO(Kernel_Fs, "nfds = {}", nfds); - fd_set read_host, write_host, except_host; FD_ZERO(&read_host); FD_ZERO(&write_host); FD_ZERO(&except_host); - std::map host_to_guest; auto* h = Common::Singleton::Instance(); - u64 max_fd = 0; + +#ifdef _WIN32 + + // Separate sockets for select() + for (auto i = 0; i < nfds; ++i) { + auto read = readfds && FD_ISSET(i, readfds); + auto write = writefds && FD_ISSET(i, writefds); + auto except = exceptfds && FD_ISSET(i, exceptfds); + if (read || write || except) { + LOG_INFO(Kernel_Fs, "guest fd {} expected", i); + auto* file = h->GetFile(i); + if (file == nullptr || + ((file->type == Core::FileSys::FileType::Regular && !file->f.IsOpen()) || + (file->type == Core::FileSys::FileType::Socket && !file->is_opened))) { + LOG_ERROR(Kernel_Fs, "fd {} is null or not opened", i); + *__Error() = POSIX_EBADF; + return -1; + } + + if (file->type != Core::FileSys::FileType::Socket) { + LOG_WARNING(Kernel_Fs, "fd {} is not a socket, ignoring", i); + continue; + } + + auto fd = [&] { + switch (file->type) { + case Core::FileSys::FileType::Socket: + return file->socket->Native(); + default: + UNREACHABLE(); + } + }(); + + if (read) { + FD_SET(fd, &read_host); + continue; + } + if (write) { + FD_SET(fd, &write_host); + continue; + } + if (except) { + FD_SET(fd, &except_host); + continue; + } + } + } + + int result = select(0, &read_host, &write_host, &except_host, reinterpret_cast(timeout)); + int total_ready = result; + + for (int fd = 0; fd < nfds; ++fd) { + auto* file = h->GetFile(fd); + + if (file->type == Core::FileSys::FileType::Socket) { + auto sock = file->socket->Native(); + if (readfds && !(FD_ISSET(sock, &read_host))) { + FD_CLR(fd, &readfds); + } + if (writefds && !(FD_ISSET(sock, &write_host))) { + FD_CLR(fd, &writefds); + } + if (exceptfds && !(FD_ISSET(sock, &except_host))) { + FD_CLR(fd, &exceptfds); + } + continue; + } + + HANDLE h = (HANDLE)_get_osfhandle(fd); + DWORD type = GetFileType(h); + if (type == FILE_TYPE_UNKNOWN) + continue; + + // READ check + if (readfds && FD_ISSET(fd, readfds)) { + if (type == FILE_TYPE_PIPE) { + DWORD avail = 0; + if (PeekNamedPipe(h, NULL, 0, NULL, &avail, NULL) && avail > 0) { + total_ready++; + } else { + FD_CLR(fd, readfds); + } + } else if (type == FILE_TYPE_DISK) { + char tmp; + long pos = _lseek(fd, 0, SEEK_CUR); + if (_read(fd, &tmp, 1) > 0) { + _lseek(fd, pos, SEEK_SET); + total_ready++; + } else { + FD_CLR(fd, readfds); + } + } + } + + // WRITE check + if (writefds && FD_ISSET(fd, writefds)) { + DWORD written = 0; + char dummy = 0; + BOOL writable = FALSE; + if (type == FILE_TYPE_PIPE) { + // Try writing 0 bytes to check if it's broken + writable = WriteFile(h, &dummy, 0, &written, NULL); + } else if (type == FILE_TYPE_DISK) { + writable = true; // Disk files are always "writable" + } + if (writable) { + total_ready++; + } else { + FD_CLR(fd, writefds); + } + } + + // EXCEPTION check + if (exceptfds && FD_ISSET(fd, exceptfds)) { + DWORD err = 0, size = sizeof(err); + BOOL error_detected = false; + + if (type == FILE_TYPE_PIPE) { + // Check broken pipe by trying non-blocking zero write + DWORD written; + char tmp = 0; + if (!WriteFile(h, &tmp, 0, &written, NULL)) { + DWORD e = GetLastError(); + if (e == ERROR_NO_DATA || e == ERROR_BROKEN_PIPE) { + error_detected = true; + } + } + } + + if (error_detected) { + total_ready++; + } else { + FD_CLR(fd, exceptfds); + } + } + } + + return total_ready; + +#else + + std::map host_to_guest; + int max_fd = 0; for (auto i = 0; i < nfds; ++i) { auto read = readfds && FD_ISSET(i, readfds); @@ -1119,12 +1259,12 @@ s32 PS4_SYSV_ABI posix_select(int nfds, fd_set* readfds, fd_set* writefds, fd_se return -1; } - u64 fd = [&] { + int fd = [&] { switch (file->type) { case Core::FileSys::FileType::Regular: - return static_cast(file->f.GetFileMapping()); + return static_cast(file->f.GetFileMapping()); case Core::FileSys::FileType::Socket: - return static_cast(file->socket->Native()); + return file->socket->Native(); default: UNREACHABLE(); } @@ -1180,6 +1320,7 @@ s32 PS4_SYSV_ABI posix_select(int nfds, fd_set* readfds, fd_set* writefds, fd_se } return ret; +#endif } void RegisterFileSystem(Core::Loader::SymbolsResolver* sym) { From 9a787dbd34599c0518d061429c5724532c4d526b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Fri, 18 Jul 2025 23:38:28 +0100 Subject: [PATCH 59/62] clang-format --- src/core/libraries/kernel/file_system.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/core/libraries/kernel/file_system.cpp b/src/core/libraries/kernel/file_system.cpp index d71219c71..ddc1b7225 100644 --- a/src/core/libraries/kernel/file_system.cpp +++ b/src/core/libraries/kernel/file_system.cpp @@ -1089,10 +1089,9 @@ s32 PS4_SYSV_ABI sceKernelUnlink(const char* path) { s32 PS4_SYSV_ABI posix_select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, OrbisKernelTimeval* timeout) { LOG_INFO(Kernel_Fs, - "nfds = {}, readfds = {:#x}, writefds = {:#x}, exceptfds = {:#x}, timeout " - "= {:#x}", - nfds, reinterpret_cast(readfds), reinterpret_cast(writefds), - reinterpret_cast(exceptfds), reinterpret_cast(timeout)); + "nfds = {}, readfds = {:#x}, writefds = {:#x}, exceptfds = {:#x}, timeout " + "= {:#x}", + nfds, fmt::ptr(readfds), fmt::ptr(writefds), fmt::ptr(exceptfds), fmt::ptr(timeout)); fd_set read_host, write_host, except_host; FD_ZERO(&read_host); @@ -1148,7 +1147,8 @@ s32 PS4_SYSV_ABI posix_select(int nfds, fd_set* readfds, fd_set* writefds, fd_se } } - int result = select(0, &read_host, &write_host, &except_host, reinterpret_cast(timeout)); + int result = + select(0, &read_host, &write_host, &except_host, reinterpret_cast(timeout)); int total_ready = result; for (int fd = 0; fd < nfds; ++fd) { From da2afe2bf9714deef0a6fec82f26d26f21797ec6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Fri, 18 Jul 2025 23:50:00 +0100 Subject: [PATCH 60/62] review fixes --- src/core/libraries/network/net.cpp | 17 ++++++++++++----- src/core/libraries/network/sys_net.cpp | 3 +-- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/core/libraries/network/net.cpp b/src/core/libraries/network/net.cpp index b3837f317..cc8391867 100644 --- a/src/core/libraries/network/net.cpp +++ b/src/core/libraries/network/net.cpp @@ -699,7 +699,6 @@ int PS4_SYSV_ABI sceNetEpollControl(OrbisNetId epollid, OrbisNetEpollFlag op, Or } #ifdef __linux__ - // const auto socket = Common::Singleton::Instance()->socks[id]; auto* h = Common::Singleton::Instance(); auto* file = h->GetFile(id); if (!file || file->type != Core::FileSys::FileType::Socket) { @@ -739,7 +738,12 @@ int PS4_SYSV_ABI sceNetEpollControl(OrbisNetId epollid, OrbisNetEpollFlag op, Or } #ifdef __linux__ - const auto socket = Common::Singleton::Instance()->socks[id]; + auto* h = Common::Singleton::Instance(); + auto* file = h->GetFile(id); + if (!file || file->type != Core::FileSys::FileType::Socket) { + return -ORBIS_NET_EBADF; + } + const auto socket = file->socket; ASSERT(epoll_ctl(epoll->epoll_fd, EPOLL_CTL_DEL, socket->Native(), nullptr) == 0); #endif epoll->events.erase(it); @@ -1220,7 +1224,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; } - LOG_DEBUG(Lib_Net, "called, af = {}"); + LOG_DEBUG(Lib_Net, "called, af = {}", af); const char* returnvalue = nullptr; switch (af) { @@ -1267,7 +1271,7 @@ int PS4_SYSV_ABI sceNetInetPton(int af, const char* src, void* dst) { int res = inet_pton(ConvertFamilies(af), src, dst); #endif if (res < 0) { - UNREACHABLE_MSG("af = {}, src = {}, dst = {:#x}", af, src, reinterpret_cast(dst)); + UNREACHABLE_MSG("af = {}, src = {}, dst = {:#x}", af, src, fmt::ptr(dst)); } return res; } @@ -1586,7 +1590,10 @@ int PS4_SYSV_ABI sceNetResolverStartNtoa(OrbisNetId resolverid, const char* host if ((flags & ORBIS_NET_RESOLVER_ASYNC) != 0) { // moves processing to EpollWait - UNREACHABLE_MSG("unimplemented"); + LOG_ERROR(Lib_Net, "async resolution is not implemented"); + *sceNetErrnoLoc() = ORBIS_NET_RESOLVER_EINTERNAL; + auto ret = -ORBIS_NET_RESOLVER_EINTERNAL | ORBIS_NET_ERROR_BASE; + return ret; } const addrinfo hints = { diff --git a/src/core/libraries/network/sys_net.cpp b/src/core/libraries/network/sys_net.cpp index f6db325ed..e6c6fe346 100644 --- a/src/core/libraries/network/sys_net.cpp +++ b/src/core/libraries/network/sys_net.cpp @@ -33,8 +33,7 @@ int PS4_SYSV_ABI sys_connect(OrbisNetId s, const OrbisNetSockaddr* addr, u32 add return -1; } int PS4_SYSV_ABI sys_bind(OrbisNetId s, const OrbisNetSockaddr* addr, u32 addrlen) { - LOG_DEBUG(Lib_Net, "s = {}, addr = {:#x}, addrlen = {}", s, reinterpret_cast(addr), - addrlen); + LOG_DEBUG(Lib_Net, "s = {}, addr = {:#x}, addrlen = {}", s, fmt::ptr(addr), addrlen); auto* h = Common::Singleton::Instance(); auto* file = h->GetFile(s); From 575d4c155ddcc0174b194ee44ace97c1896942c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Sat, 19 Jul 2025 13:54:58 +0100 Subject: [PATCH 61/62] code review --- src/core/libraries/kernel/file_system.cpp | 15 ++++++--------- src/core/libraries/kernel/kernel.cpp | 2 ++ src/core/libraries/network/net.cpp | 2 +- src/core/libraries/network/sys_net.cpp | 12 +++++++++++- src/core/libraries/network/sys_net.h | 2 ++ 5 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/core/libraries/kernel/file_system.cpp b/src/core/libraries/kernel/file_system.cpp index ddc1b7225..cb85d1bc2 100644 --- a/src/core/libraries/kernel/file_system.cpp +++ b/src/core/libraries/kernel/file_system.cpp @@ -1088,9 +1088,7 @@ s32 PS4_SYSV_ABI sceKernelUnlink(const char* path) { s32 PS4_SYSV_ABI posix_select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, OrbisKernelTimeval* timeout) { - LOG_INFO(Kernel_Fs, - "nfds = {}, readfds = {:#x}, writefds = {:#x}, exceptfds = {:#x}, timeout " - "= {:#x}", + LOG_INFO(Kernel_Fs, "nfds = {}, readfds = {}, writefds = {}, exceptfds = {}, timeout = {}", nfds, fmt::ptr(readfds), fmt::ptr(writefds), fmt::ptr(exceptfds), fmt::ptr(timeout)); fd_set read_host, write_host, except_host; @@ -1249,7 +1247,7 @@ s32 PS4_SYSV_ABI posix_select(int nfds, fd_set* readfds, fd_set* writefds, fd_se auto write = writefds && FD_ISSET(i, writefds); auto except = exceptfds && FD_ISSET(i, exceptfds); if (read || write || except) { - LOG_INFO(Kernel_Fs, "guest fd {} expected", i); + LOG_DEBUG(Kernel_Fs, "guest fd {} expected", i); auto* file = h->GetFile(i); if (file == nullptr || ((file->type == Core::FileSys::FileType::Regular && !file->f.IsOpen()) || @@ -1288,9 +1286,8 @@ s32 PS4_SYSV_ABI posix_select(int nfds, fd_set* readfds, fd_set* writefds, fd_se } } - LOG_INFO(Kernel_Fs, "calling select"); int ret = select(max_fd + 1, &read_host, &write_host, &except_host, (timeval*)timeout); - LOG_INFO(Kernel_Fs, "select = {}", ret); + LOG_DEBUG(Kernel_Fs, "select = {}", ret); if (ret > 0) { if (readfds) { @@ -1305,15 +1302,15 @@ s32 PS4_SYSV_ABI posix_select(int nfds, fd_set* readfds, fd_set* writefds, fd_se for (auto i = 0; i < max_fd + 1; ++i) { if (FD_ISSET(i, &read_host)) { - LOG_INFO(Kernel_Fs, "host fd {} (guest {}) ready for reading", i, host_to_guest[i]); + LOG_DEBUG(Kernel_Fs, "host fd {} (guest {}) ready for reading", i, host_to_guest[i]); FD_SET(host_to_guest[i], readfds); } if (FD_ISSET(i, &write_host)) { - LOG_INFO(Kernel_Fs, "host fd {} (guest {}) ready for writing", i, host_to_guest[i]); + LOG_DEBUG(Kernel_Fs, "host fd {} (guest {}) ready for writing", i, host_to_guest[i]); FD_SET(host_to_guest[i], writefds); } if (FD_ISSET(i, &except_host)) { - LOG_INFO(Kernel_Fs, "host fd {} (guest {}) ready for except", i, host_to_guest[i]); + LOG_DEBUG(Kernel_Fs, "host fd {} (guest {}) ready for except", i, host_to_guest[i]); FD_SET(host_to_guest[i], exceptfds); } } diff --git a/src/core/libraries/kernel/kernel.cpp b/src/core/libraries/kernel/kernel.cpp index f72fcd9e0..5fc8722c2 100644 --- a/src/core/libraries/kernel/kernel.cpp +++ b/src/core/libraries/kernel/kernel.cpp @@ -293,7 +293,9 @@ void RegisterLib(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("pxnCmagrtao", "libkernel", 1, "libkernel", 1, 1, Libraries::Net::sys_listen); LIB_FUNCTION("3e+4Iv7IJ8U", "libkernel", 1, "libkernel", 1, 1, Libraries::Net::sys_accept); LIB_FUNCTION("TU-d9PfIHPM", "libScePosix", 1, "libkernel", 1, 1, Libraries::Net::sys_socket); + LIB_FUNCTION("fZOeZIOEmLw", "libScePosix", 1, "libkernel", 1, 1, Libraries::Net::sys_send); LIB_FUNCTION("oBr313PppNE", "libScePosix", 1, "libkernel", 1, 1, Libraries::Net::sys_sendto); + LIB_FUNCTION("Ez8xjo9UF4E", "libScePosix", 1, "libkernel", 1, 1, Libraries::Net::sys_recv); LIB_FUNCTION("lUk6wrGXyMw", "libScePosix", 1, "libkernel", 1, 1, Libraries::Net::sys_recvfrom); LIB_FUNCTION("fFxGkxF2bVo", "libScePosix", 1, "libkernel", 1, 1, Libraries::Net::sys_setsockopt); diff --git a/src/core/libraries/network/net.cpp b/src/core/libraries/network/net.cpp index cc8391867..d90de1529 100644 --- a/src/core/libraries/network/net.cpp +++ b/src/core/libraries/network/net.cpp @@ -1271,7 +1271,7 @@ int PS4_SYSV_ABI sceNetInetPton(int af, const char* src, void* dst) { int res = inet_pton(ConvertFamilies(af), src, dst); #endif if (res < 0) { - UNREACHABLE_MSG("af = {}, src = {}, dst = {:#x}", af, src, fmt::ptr(dst)); + UNREACHABLE_MSG("af = {}, src = {}, dst = {}", af, src, fmt::ptr(dst)); } return res; } diff --git a/src/core/libraries/network/sys_net.cpp b/src/core/libraries/network/sys_net.cpp index e6c6fe346..19bf4d88b 100644 --- a/src/core/libraries/network/sys_net.cpp +++ b/src/core/libraries/network/sys_net.cpp @@ -33,7 +33,7 @@ int PS4_SYSV_ABI sys_connect(OrbisNetId s, const OrbisNetSockaddr* addr, u32 add return -1; } int PS4_SYSV_ABI sys_bind(OrbisNetId s, const OrbisNetSockaddr* addr, u32 addrlen) { - LOG_DEBUG(Lib_Net, "s = {}, addr = {:#x}, addrlen = {}", s, fmt::ptr(addr), addrlen); + LOG_DEBUG(Lib_Net, "s = {}, addr = {}, addrlen = {}", s, fmt::ptr(addr), addrlen); auto* h = Common::Singleton::Instance(); auto* file = h->GetFile(s); @@ -247,6 +247,11 @@ int PS4_SYSV_ABI sys_socketclose(OrbisNetId s) { LOG_ERROR(Lib_Net, "error code returned : {:#x}", (u32)returncode); return -1; } + +int PS4_SYSV_ABI sys_send(OrbisNetId s, const void* buf, u64 len, int flags) { + return sys_sendto(s, buf, len, flags, nullptr, 0); +} + int PS4_SYSV_ABI sys_sendto(OrbisNetId s, const void* buf, u64 len, int flags, const OrbisNetSockaddr* addr, u32 addrlen) { LOG_WARNING(Lib_Net, "s = {}, len = {}, flags = {:#x}, addrlen = {}", s, len, flags, addrlen); @@ -271,6 +276,11 @@ int PS4_SYSV_ABI sys_sendmsg(OrbisNetId s, const OrbisNetMsghdr* msg, int flags) LOG_ERROR(Lib_Net, "(STUBBED) called"); return -1; } + +int PS4_SYSV_ABI sys_recv(OrbisNetId s, void* buf, u64 len, int flags) { + return sys_recvfrom(s, buf, len, flags, nullptr, 0); +} + int PS4_SYSV_ABI sys_recvfrom(OrbisNetId s, void* buf, u64 len, int flags, OrbisNetSockaddr* addr, u32* paddrlen) { // LOG_INFO(Lib_Net, "s = {}, buf = {:#x}, len = {}, flags = {:#x}", s, diff --git a/src/core/libraries/network/sys_net.h b/src/core/libraries/network/sys_net.h index c23152de1..93913140c 100644 --- a/src/core/libraries/network/sys_net.h +++ b/src/core/libraries/network/sys_net.h @@ -22,9 +22,11 @@ int PS4_SYSV_ABI sys_socketex(const char* name, int family, int type, int protoc int PS4_SYSV_ABI sys_socket(int family, int type, int protocol); int PS4_SYSV_ABI sys_netabort(OrbisNetId s, int flags); int PS4_SYSV_ABI sys_socketclose(OrbisNetId s); +int PS4_SYSV_ABI sys_send(OrbisNetId s, const void* buf, u64 len, int flags); int PS4_SYSV_ABI sys_sendto(OrbisNetId s, const void* buf, u64 len, int flags, const OrbisNetSockaddr* addr, u32 addrlen); int PS4_SYSV_ABI sys_sendmsg(OrbisNetId s, const OrbisNetMsghdr* msg, int flags); +int PS4_SYSV_ABI sys_recv(OrbisNetId s, void* buf, u64 len, int flags); int PS4_SYSV_ABI sys_recvfrom(OrbisNetId s, void* buf, u64 len, int flags, OrbisNetSockaddr* addr, u32* paddrlen); int PS4_SYSV_ABI sys_recvmsg(OrbisNetId s, OrbisNetMsghdr* msg, int flags); From 76d9bf9bf50f1ca93d8545fd31c2df8d73449fc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Sun, 20 Jul 2025 15:19:39 +0100 Subject: [PATCH 62/62] return ssize_t from recv functions --- src/core/libraries/network/sys_net.cpp | 6 +++--- src/core/libraries/network/sys_net.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/core/libraries/network/sys_net.cpp b/src/core/libraries/network/sys_net.cpp index 19bf4d88b..a70a9358b 100644 --- a/src/core/libraries/network/sys_net.cpp +++ b/src/core/libraries/network/sys_net.cpp @@ -277,11 +277,11 @@ int PS4_SYSV_ABI sys_sendmsg(OrbisNetId s, const OrbisNetMsghdr* msg, int flags) return -1; } -int PS4_SYSV_ABI sys_recv(OrbisNetId s, void* buf, u64 len, int flags) { +ssize_t PS4_SYSV_ABI sys_recv(OrbisNetId s, void* buf, u64 len, int flags) { return sys_recvfrom(s, buf, len, flags, nullptr, 0); } -int PS4_SYSV_ABI sys_recvfrom(OrbisNetId s, void* buf, u64 len, int flags, OrbisNetSockaddr* addr, +ssize_t PS4_SYSV_ABI sys_recvfrom(OrbisNetId s, void* buf, u64 len, int flags, OrbisNetSockaddr* addr, u32* paddrlen) { // LOG_INFO(Lib_Net, "s = {}, buf = {:#x}, len = {}, flags = {:#x}", s, // reinterpret_cast(buf), len, flags); @@ -302,7 +302,7 @@ int PS4_SYSV_ABI sys_recvfrom(OrbisNetId s, void* buf, u64 len, int flags, Orbis // LOG_ERROR(Lib_Net, "error code returned : {:#x}", (u32)returncode); return -1; } -int PS4_SYSV_ABI sys_recvmsg(OrbisNetId s, OrbisNetMsghdr* msg, int flags) { +ssize_t PS4_SYSV_ABI sys_recvmsg(OrbisNetId s, OrbisNetMsghdr* msg, int flags) { LOG_ERROR(Lib_Net, "(STUBBED) called"); return -1; } diff --git a/src/core/libraries/network/sys_net.h b/src/core/libraries/network/sys_net.h index 93913140c..927c9ebab 100644 --- a/src/core/libraries/network/sys_net.h +++ b/src/core/libraries/network/sys_net.h @@ -26,8 +26,8 @@ int PS4_SYSV_ABI sys_send(OrbisNetId s, const void* buf, u64 len, int flags); int PS4_SYSV_ABI sys_sendto(OrbisNetId s, const void* buf, u64 len, int flags, const OrbisNetSockaddr* addr, u32 addrlen); int PS4_SYSV_ABI sys_sendmsg(OrbisNetId s, const OrbisNetMsghdr* msg, int flags); -int PS4_SYSV_ABI sys_recv(OrbisNetId s, void* buf, u64 len, int flags); -int PS4_SYSV_ABI sys_recvfrom(OrbisNetId s, void* buf, u64 len, int flags, OrbisNetSockaddr* addr, +ssize_t PS4_SYSV_ABI sys_recv(OrbisNetId s, void* buf, u64 len, int flags); +ssize_t PS4_SYSV_ABI sys_recvfrom(OrbisNetId s, void* buf, u64 len, int flags, OrbisNetSockaddr* addr, u32* paddrlen); -int PS4_SYSV_ABI sys_recvmsg(OrbisNetId s, OrbisNetMsghdr* msg, int flags); +ssize_t PS4_SYSV_ABI sys_recvmsg(OrbisNetId s, OrbisNetMsghdr* msg, int flags); } // namespace Libraries::Net \ No newline at end of file