diff --git a/src/core/libraries/network/net.cpp b/src/core/libraries/network/net.cpp index 3f3f6b8e8..ff6a703c8 100644 --- a/src/core/libraries/network/net.cpp +++ b/src/core/libraries/network/net.cpp @@ -886,8 +886,45 @@ int PS4_SYSV_ABI sceNetGetsockname(OrbisNetId s, OrbisNetSockaddr* addr, u32* pa } int PS4_SYSV_ABI sceNetGetsockopt(OrbisNetId s, int level, int optname, void* optval, u32* optlen) { - LOG_ERROR(Lib_Net, "(STUBBED) called"); - return ORBIS_OK; + if (!g_isNetInitialized) { + return ORBIS_NET_ERROR_ENOTINIT; + } + int result; + int err; + int positiveErr; + + do { + result = sys_getsockopt(s, level, optname, optval, optlen); + + if (result >= 0) { + return result; // Success + } + + err = *Libraries::Kernel::__Error(); // Standard errno + + // Convert to positive error for comparison + int positiveErr = (err < 0) ? -err : err; + + if ((positiveErr & 0xfff0000) != 0) { + // Unknown/fatal error range + *sceNetErrnoLoc() = ORBIS_NET_ERETURN; + return -positiveErr; + } + + // Retry if interrupted + } while (positiveErr == ORBIS_NET_EINTR); + + if (positiveErr == ORBIS_NET_EADDRINUSE) { + result = -ORBIS_NET_EBADF; + } else if (positiveErr == ORBIS_NET_EALREADY) { + result = -ORBIS_NET_EINTR; + } else { + result = -positiveErr; + } + + *sceNetErrnoLoc() = -result; + + return (-result) | ORBIS_NET_ERROR_BASE; // Convert to official ORBIS_NET_ERROR code } int PS4_SYSV_ABI sceNetGetStatisticsInfo() { @@ -981,9 +1018,46 @@ int PS4_SYSV_ABI sceNetIoctl() { return ORBIS_OK; } -int PS4_SYSV_ABI sceNetListen() { - LOG_ERROR(Lib_Net, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceNetListen(OrbisNetId s, int backlog) { + if (!g_isNetInitialized) { + return ORBIS_NET_ERROR_ENOTINIT; + } + int result; + int err; + int positiveErr; + + do { + result = sys_listen(s, backlog); + + if (result >= 0) { + return result; // Success + } + + err = *Libraries::Kernel::__Error(); // Standard errno + + // Convert to positive error for comparison + int positiveErr = (err < 0) ? -err : err; + + if ((positiveErr & 0xfff0000) != 0) { + // Unknown/fatal error range + *sceNetErrnoLoc() = ORBIS_NET_ERETURN; + return -positiveErr; + } + + // Retry if interrupted + } while (positiveErr == ORBIS_NET_EINTR); + + if (positiveErr == ORBIS_NET_EADDRINUSE) { + result = -ORBIS_NET_EBADF; + } else if (positiveErr == ORBIS_NET_EALREADY) { + result = -ORBIS_NET_EINTR; + } else { + result = -positiveErr; + } + + *sceNetErrnoLoc() = -result; + + return (-result) | ORBIS_NET_ERROR_BASE; // Convert to official ORBIS_NET_ERROR code } int PS4_SYSV_ABI sceNetMemoryAllocate() { @@ -1150,9 +1224,47 @@ int PS4_SYSV_ABI sceNetSetDnsInfoToKernel() { return ORBIS_OK; } -int PS4_SYSV_ABI sceNetSetsockopt() { - LOG_ERROR(Lib_Net, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceNetSetsockopt(OrbisNetId s, int level, int optname, const void* optval, + u32 optlen) { + if (!g_isNetInitialized) { + return ORBIS_NET_ERROR_ENOTINIT; + } + int result; + int err; + int positiveErr; + + do { + result = sys_setsockopt(s, level, optname, optval, optlen); + + if (result >= 0) { + return result; // Success + } + + err = *Libraries::Kernel::__Error(); // Standard errno + + // Convert to positive error for comparison + int positiveErr = (err < 0) ? -err : err; + + if ((positiveErr & 0xfff0000) != 0) { + // Unknown/fatal error range + *sceNetErrnoLoc() = ORBIS_NET_ERETURN; + return -positiveErr; + } + + // Retry if interrupted + } while (positiveErr == ORBIS_NET_EINTR); + + if (positiveErr == ORBIS_NET_EADDRINUSE) { + result = -ORBIS_NET_EBADF; + } else if (positiveErr == ORBIS_NET_EALREADY) { + result = -ORBIS_NET_EINTR; + } else { + result = -positiveErr; + } + + *sceNetErrnoLoc() = -result; + + return (-result) | ORBIS_NET_ERROR_BASE; // Convert to official ORBIS_NET_ERROR code } int PS4_SYSV_ABI sceNetShowIfconfig() { diff --git a/src/core/libraries/network/net.h b/src/core/libraries/network/net.h index c1f81d53f..7fb794498 100644 --- a/src/core/libraries/network/net.h +++ b/src/core/libraries/network/net.h @@ -178,7 +178,7 @@ int PS4_SYSV_ABI sceNetInfoDumpStop(); int PS4_SYSV_ABI sceNetInit(); int PS4_SYSV_ABI sceNetInitParam(); int PS4_SYSV_ABI sceNetIoctl(); -int PS4_SYSV_ABI sceNetListen(); +int PS4_SYSV_ABI sceNetListen(OrbisNetId s, int backlog); int PS4_SYSV_ABI sceNetMemoryAllocate(); int PS4_SYSV_ABI sceNetMemoryFree(); u32 PS4_SYSV_ABI sceNetNtohl(u32 net32); @@ -213,7 +213,8 @@ int PS4_SYSV_ABI sceNetSetDns6Info(); int PS4_SYSV_ABI sceNetSetDns6InfoToKernel(); int PS4_SYSV_ABI sceNetSetDnsInfo(); int PS4_SYSV_ABI sceNetSetDnsInfoToKernel(); -int PS4_SYSV_ABI sceNetSetsockopt(); +int PS4_SYSV_ABI sceNetSetsockopt(OrbisNetId s, int level, int optname, const void* optval, + u32 optlen); int PS4_SYSV_ABI sceNetShowIfconfig(); int PS4_SYSV_ABI sceNetShowIfconfigForBuffer(); int PS4_SYSV_ABI sceNetShowIfconfigWithMemory(); diff --git a/src/core/libraries/network/sys_net.cpp b/src/core/libraries/network/sys_net.cpp index a02746ab4..107224b7c 100644 --- a/src/core/libraries/network/sys_net.cpp +++ b/src/core/libraries/network/sys_net.cpp @@ -20,4 +20,13 @@ int sys_getpeername(OrbisNetId s, const OrbisNetSockaddr* addr, u32* paddrlen) { int sys_getsockname(OrbisNetId s, const OrbisNetSockaddr* addr, u32* paddrlen) { return -1; } +int sys_getsockopt(OrbisNetId s, int level, int optname, void* optval, u32* optlen) { + return -1; +} +int sys_listen(OrbisNetId s, int backlog) { + return -1; +} +int sys_setsockopt(OrbisNetId s, int level, int optname, const void* optval, u32 optlen) { + return -1; +} } // namespace Libraries::Net \ No newline at end of file diff --git a/src/core/libraries/network/sys_net.h b/src/core/libraries/network/sys_net.h index 0245018d0..b7dc1d947 100644 --- a/src/core/libraries/network/sys_net.h +++ b/src/core/libraries/network/sys_net.h @@ -13,5 +13,7 @@ int sys_bind(OrbisNetId s, const OrbisNetSockaddr* addr, u32 addrlen); int sys_accept(OrbisNetId s, const OrbisNetSockaddr* addr, u32* paddrlen); int sys_getpeername(OrbisNetId s, const OrbisNetSockaddr* addr, u32* paddrlen); int sys_getsockname(OrbisNetId s, const OrbisNetSockaddr* addr, u32* paddrlen); - +int sys_getsockopt(OrbisNetId s, int level, int optname, void* optval, u32* optlen); +int sys_listen(OrbisNetId s, int backlog); +int sys_setsockopt(OrbisNetId s, int level, int optname, const void* optval, u32 optlen); } // namespace Libraries::Net \ No newline at end of file