Sockets fixes (#3392)

* Print errnos as decimal

* SetSocketOptions: prevent setting SO_TYPE

* Extract net error handler

* Change the local IP retrieval method

* Fix windows
This commit is contained in:
Marcin Mikołajczyk
2025-08-06 07:00:29 +02:00
committed by GitHub
parent 074dfe2571
commit 2f701311f2
7 changed files with 131 additions and 658 deletions

View File

@@ -40,6 +40,45 @@ static int ConvertFamilies(int family) {
}
}
auto NetErrorHandler(auto f) -> decltype(f()) {
auto result = 0;
int err;
int positiveErr;
do {
result = f();
if (result >= 0) {
return result; // Success
}
err = *Libraries::Kernel::__Error(); // Standard errno
// Convert to positive error for comparison
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_ENOTSOCK) {
result = -ORBIS_NET_EBADF;
} else if (positiveErr == ORBIS_NET_ENETINTR) {
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 in6addr_any() {
LOG_ERROR(Lib_Net, "(STUBBED) called");
return ORBIS_OK;
@@ -84,42 +123,8 @@ OrbisNetId PS4_SYSV_ABI sceNetAccept(OrbisNetId s, OrbisNetSockaddr* addr, u32*
if (!g_isNetInitialized) {
return ORBIS_NET_ERROR_ENOTINIT;
}
int result;
int err;
int positiveErr;
do {
result = sys_accept(s, addr, paddrlen);
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
return NetErrorHandler([&] { return sys_accept(s, addr, paddrlen); });
}
int PS4_SYSV_ABI sceNetAddrConfig6GetInfo() {
@@ -181,42 +186,8 @@ int PS4_SYSV_ABI sceNetBind(OrbisNetId s, const OrbisNetSockaddr* addr, u32 addr
if (!g_isNetInitialized) {
return ORBIS_NET_ERROR_ENOTINIT;
}
int result;
int err;
int positiveErr;
do {
result = sys_bind(s, addr, addrlen);
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
return NetErrorHandler([&] { return sys_bind(s, addr, addrlen); });
}
int PS4_SYSV_ABI sceNetClearDnsCache() {
@@ -563,42 +534,8 @@ int PS4_SYSV_ABI sceNetConnect(OrbisNetId s, const OrbisNetSockaddr* addr, u32 a
if (!g_isNetInitialized) {
return ORBIS_NET_ERROR_ENOTINIT;
}
int result;
int err;
int positiveErr;
do {
result = sys_connect(s, addr, addrlen);
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
return NetErrorHandler([&] { return sys_connect(s, addr, addrlen); });
}
int PS4_SYSV_ABI sceNetControl() {
@@ -797,42 +734,8 @@ int PS4_SYSV_ABI sceNetGetpeername(OrbisNetId s, OrbisNetSockaddr* addr, u32* pa
if (!g_isNetInitialized) {
return ORBIS_NET_ERROR_ENOTINIT;
}
int result;
int err;
int positiveErr;
do {
result = sys_getpeername(s, addr, paddrlen);
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
return NetErrorHandler([&] { return sys_getpeername(s, addr, paddrlen); });
}
int PS4_SYSV_ABI sceNetGetRandom() {
@@ -859,42 +762,8 @@ int PS4_SYSV_ABI sceNetGetsockname(OrbisNetId s, OrbisNetSockaddr* addr, u32* pa
if (!g_isNetInitialized) {
return ORBIS_NET_ERROR_ENOTINIT;
}
int result;
int err;
int positiveErr;
do {
result = sys_getsockname(s, addr, paddrlen);
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
return NetErrorHandler([&] { return sys_getsockname(s, addr, paddrlen); });
}
int PS4_SYSV_ABI sceNetGetsockopt(OrbisNetId s, int level, int optname, void* optval, u32* optlen) {
@@ -902,42 +771,8 @@ int PS4_SYSV_ABI sceNetGetsockopt(OrbisNetId s, int level, int optname, void* op
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
return NetErrorHandler([&] { return sys_getsockopt(s, level, optname, optval, optlen); });
}
int PS4_SYSV_ABI sceNetGetStatisticsInfo() {
@@ -1167,42 +1002,8 @@ 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
return NetErrorHandler([&] { return sys_listen(s, backlog); });
}
int PS4_SYSV_ABI sceNetMemoryAllocate() {
@@ -1252,42 +1053,9 @@ int PS4_SYSV_ABI sceNetRecv(OrbisNetId s, void* buf, u64 len, int flags) {
if (!g_isNetInitialized) {
return ORBIS_NET_ERROR_ENOTINIT;
}
int result;
int err;
int positiveErr;
do {
result = sys_recvfrom(s, buf, len, flags | 0x40000000, nullptr, 0);
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
return NetErrorHandler(
[&] { return sys_recvfrom(s, buf, len, flags | 0x40000000, nullptr, 0); });
}
int PS4_SYSV_ABI sceNetRecvfrom(OrbisNetId s, void* buf, u64 len, int flags, OrbisNetSockaddr* addr,
@@ -1295,84 +1063,17 @@ int PS4_SYSV_ABI sceNetRecvfrom(OrbisNetId s, void* buf, u64 len, int flags, Orb
if (!g_isNetInitialized) {
return ORBIS_NET_ERROR_ENOTINIT;
}
int result;
int err;
int positiveErr;
do {
result = sys_recvfrom(s, buf, len, flags | 0x40000000, addr, paddrlen);
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
return NetErrorHandler(
[&] { return sys_recvfrom(s, buf, len, flags | 0x40000000, addr, paddrlen); });
}
int PS4_SYSV_ABI sceNetRecvmsg(OrbisNetId s, OrbisNetMsghdr* msg, int flags) {
if (!g_isNetInitialized) {
return ORBIS_NET_ERROR_ENOTINIT;
}
int result;
int err;
int positiveErr;
do {
result = sys_recvmsg(s, msg, flags | 0x40000000);
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
return NetErrorHandler([&] { return sys_recvmsg(s, msg, flags | 0x40000000); });
}
int PS4_SYSV_ABI sceNetResolverAbort() {
@@ -1496,84 +1197,16 @@ int PS4_SYSV_ABI sceNetSend(OrbisNetId s, const void* buf, u64 len, int flags) {
if (!g_isNetInitialized) {
return ORBIS_NET_ERROR_ENOTINIT;
}
int result;
int err;
int positiveErr;
do {
result = sys_sendto(s, buf, len, flags | 0x40020000, nullptr, 0);
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
return NetErrorHandler([&] { return sys_sendto(s, buf, len, flags | 0x40020000, nullptr, 0); });
}
int PS4_SYSV_ABI sceNetSendmsg(OrbisNetId s, const OrbisNetMsghdr* msg, int flags) {
if (!g_isNetInitialized) {
return ORBIS_NET_ERROR_ENOTINIT;
}
int result;
int err;
int positiveErr;
do {
result = sys_sendmsg(s, msg, flags | 0x40020000);
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
return NetErrorHandler([&] { return sys_sendmsg(s, msg, flags | 0x40020000); });
}
int PS4_SYSV_ABI sceNetSendto(OrbisNetId s, const void* buf, u64 len, int flags,
@@ -1581,42 +1214,9 @@ int PS4_SYSV_ABI sceNetSendto(OrbisNetId s, const void* buf, u64 len, int flags,
if (!g_isNetInitialized) {
return ORBIS_NET_ERROR_ENOTINIT;
}
int result;
int err;
int positiveErr;
do {
result = sys_sendto(s, buf, len, flags | 0x40020000, addr, addrlen);
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
return NetErrorHandler(
[&] { return sys_sendto(s, buf, len, flags | 0x40020000, addr, addrlen); });
}
int PS4_SYSV_ABI sceNetSetDns6Info() {
@@ -1645,42 +1245,8 @@ int PS4_SYSV_ABI sceNetSetsockopt(OrbisNetId s, int level, int optname, const vo
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
return NetErrorHandler([&] { return sys_setsockopt(s, level, optname, optval, optlen); });
}
int PS4_SYSV_ABI sceNetShowIfconfig() {
@@ -1767,168 +1333,32 @@ int PS4_SYSV_ABI sceNetShutdown(OrbisNetId s, int how) {
if (!g_isNetInitialized) {
return ORBIS_NET_ERROR_ENOTINIT;
}
int result;
int err;
int positiveErr;
do {
result = sys_shutdown(s, how);
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
return NetErrorHandler([&] { return sys_shutdown(s, how); });
}
OrbisNetId PS4_SYSV_ABI sceNetSocket(const char* name, int family, int type, int protocol) {
if (!g_isNetInitialized) {
return ORBIS_NET_ERROR_ENOTINIT;
}
int result;
int err;
int positiveErr;
do {
result = sys_socketex(name, family, type, protocol);
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
return NetErrorHandler([&] { return sys_socketex(name, family, type, protocol); });
}
int PS4_SYSV_ABI sceNetSocketAbort(OrbisNetId s, int flags) {
if (!g_isNetInitialized) {
return ORBIS_NET_ERROR_ENOTINIT;
}
int result;
int err;
int positiveErr;
do {
result = sys_netabort(s, flags);
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
return NetErrorHandler([&] { return sys_netabort(s, flags); });
}
int PS4_SYSV_ABI sceNetSocketClose(OrbisNetId s) {
if (!g_isNetInitialized) {
return ORBIS_NET_ERROR_ENOTINIT;
}
int result;
int err;
int positiveErr;
do {
result = sys_socketclose(s);
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
return NetErrorHandler([&] { return sys_socketclose(s); });
}
int PS4_SYSV_ABI sceNetSyncCreate() {

View File

@@ -58,6 +58,7 @@ constexpr int ORBIS_NET_EINACTIVEDISABLED = 163;
constexpr int ORBIS_NET_ENODATA = 164;
constexpr int ORBIS_NET_EDESC = 165;
constexpr int ORBIS_NET_EDESCTIMEDOUT = 166;
constexpr int ORBIS_NET_ENETINTR = 167;
constexpr int ORBIS_NET_ENOTINIT = 200;
constexpr int ORBIS_NET_ENOLIBMEM = 201;
constexpr int ORBIS_NET_ECALLBACK = 203;

View File

@@ -322,4 +322,49 @@ bool NetUtilInternal::RetrieveNetmask() {
return success;
}
const std::string& NetUtilInternal::GetIp() const {
return ip;
}
bool NetUtilInternal::RetrieveIp() {
std::scoped_lock lock{m_mutex};
auto sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
return false;
}
sockaddr_in sa{};
socklen_t sa_len{sizeof(sa)};
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = inet_addr("1.1.1.1");
sa.sin_port = htons(80);
#ifdef _WIN32
#define close closesocket
#endif
if (connect(sockfd, (sockaddr*)&sa, sa_len) == -1) {
close(sockfd);
return false;
}
if (getsockname(sockfd, (struct sockaddr*)&sa, &sa_len) == -1) {
close(sockfd);
return false;
}
char netmaskStr[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &sa.sin_addr, netmaskStr, INET_ADDRSTRLEN);
ip = netmaskStr;
close(sockfd);
#ifdef _WIN32
#undef close
#endif
return true;
}
} // namespace NetUtil

View File

@@ -17,14 +17,17 @@ private:
std::array<u8, 6> ether_address{};
std::string default_gateway{};
std::string netmask{};
std::string ip{};
std::mutex m_mutex;
public:
const std::array<u8, 6>& GetEthernetAddr() const;
const std::string& GetDefaultGateway() const;
const std::string& GetNetmask() const;
const std::string& GetIp() const;
bool RetrieveEthernetAddr();
bool RetrieveDefaultGateway();
bool RetrieveNetmask();
bool RetrieveIp();
};
} // namespace NetUtil

View File

@@ -185,19 +185,12 @@ int PS4_SYSV_ABI sceNetCtlGetInfo(int code, OrbisNetCtlInfo* info) {
break;
case ORBIS_NET_CTL_INFO_IP_ADDRESS: {
strcpy(info->ip_address,
"127.0.0.1"); // placeholder in case gethostbyname can't find another ip
char devname[80];
gethostname(devname, 80);
if (struct hostent* resolved = gethostbyname(devname)) {
for (int i = 0; resolved->h_addr_list[i] != nullptr; ++i) {
struct in_addr addrIn;
memcpy(&addrIn, resolved->h_addr_list[i], sizeof(u32));
char* addr = inet_ntoa(addrIn);
if (strcmp(addr, "127.0.0.1") != 0) {
strcpy(info->ip_address, addr);
break;
}
}
"127.0.0.1"); // placeholder in case ip retrieval failed
auto success = netinfo->RetrieveIp();
if (success) {
strncpy(info->ip_address, netinfo->GetIp().data(), sizeof(info->ip_address));
} else {
LOG_WARNING(Lib_NetCtl, "local ip: failed to retrieve");
}
break;
}
@@ -214,8 +207,9 @@ int PS4_SYSV_ABI sceNetCtlGetInfo(int code, OrbisNetCtlInfo* info) {
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);
strncpy(info->default_route, netinfo->GetDefaultGateway().data(),
sizeof(info->default_route));
LOG_DEBUG(Lib_NetCtl, "default gateway: {}", info->default_route);
} else {
LOG_WARNING(Lib_NetCtl, "default gateway: failed to retrieve");
}
@@ -234,8 +228,8 @@ int PS4_SYSV_ABI sceNetCtlGetInfo(int code, OrbisNetCtlInfo* info) {
LOG_DEBUG(Lib_NetCtl, "http secondary dns: {}", info->secondary_dns);
break;
case ORBIS_NET_CTL_INFO_HTTP_PROXY_SERVER:
strcpy(info->http_proxy_server, "0.0.0.0");
LOG_DEBUG(Lib_NetCtl, "http proxy server: {}", info->http_proxy_server);
info->http_proxy_server[0] = '\0';
LOG_DEBUG(Lib_NetCtl, "http proxy server: none");
break;
case ORBIS_NET_CTL_INFO_HTTP_PROXY_PORT:
info->http_proxy_port = 0;

View File

@@ -286,12 +286,12 @@ int PosixSocket::SetSocketOptions(int level, int optname, const void* optval, u3
CASE_SETSOCKOPT(SO_RCVBUF);
CASE_SETSOCKOPT(SO_SNDTIMEO);
CASE_SETSOCKOPT(SO_RCVTIMEO);
CASE_SETSOCKOPT(SO_TYPE);
CASE_SETSOCKOPT_VALUE(ORBIS_NET_SO_CONNECTTIMEO, &sockopt_so_connecttimeo);
CASE_SETSOCKOPT_VALUE(ORBIS_NET_SO_REUSEPORT, &sockopt_so_reuseport);
CASE_SETSOCKOPT_VALUE(ORBIS_NET_SO_ONESBCAST, &sockopt_so_onesbcast);
CASE_SETSOCKOPT_VALUE(ORBIS_NET_SO_USECRYPTO, &sockopt_so_usecrypto);
CASE_SETSOCKOPT_VALUE(ORBIS_NET_SO_USESIGNATURE, &sockopt_so_usesignature);
case ORBIS_NET_SO_TYPE:
case ORBIS_NET_SO_ERROR: {
*Libraries::Kernel::__Error() = ORBIS_NET_ENOPROTOOPT;
return -1;

View File

@@ -26,7 +26,7 @@ int PS4_SYSV_ABI sys_connect(OrbisNetId s, const OrbisNetSockaddr* addr, u32 add
if (returncode >= 0) {
return returncode;
}
LOG_ERROR(Lib_Net, "error code returned : {:#x}", (u32)*Libraries::Kernel::__Error());
LOG_ERROR(Lib_Net, "error code returned: {}", (u32)*Libraries::Kernel::__Error());
return -1;
}
@@ -41,7 +41,7 @@ int PS4_SYSV_ABI sys_bind(OrbisNetId s, const OrbisNetSockaddr* addr, u32 addrle
if (returncode >= 0) {
return returncode;
}
LOG_ERROR(Lib_Net, "error code returned : {:#x}", (u32)*Libraries::Kernel::__Error());
LOG_ERROR(Lib_Net, "error code returned: {}", (u32)*Libraries::Kernel::__Error());
return -1;
}
@@ -79,7 +79,7 @@ int PS4_SYSV_ABI sys_getpeername(OrbisNetId s, OrbisNetSockaddr* addr, u32* padd
if (returncode >= 0) {
return returncode;
}
LOG_ERROR(Lib_Net, "error code returned : {:#x}", (u32)*Libraries::Kernel::__Error());
LOG_ERROR(Lib_Net, "error code returned: {}", (u32)*Libraries::Kernel::__Error());
return -1;
}
@@ -94,7 +94,7 @@ int PS4_SYSV_ABI sys_getsockname(OrbisNetId s, OrbisNetSockaddr* addr, u32* padd
if (returncode >= 0) {
return returncode;
}
LOG_ERROR(Lib_Net, "error code returned : {:#x}", (u32)*Libraries::Kernel::__Error());
LOG_ERROR(Lib_Net, "error code returned: {}", (u32)*Libraries::Kernel::__Error());
return -1;
}
@@ -109,7 +109,7 @@ int PS4_SYSV_ABI sys_getsockopt(OrbisNetId s, int level, int optname, void* optv
if (returncode >= 0) {
return returncode;
}
LOG_ERROR(Lib_Net, "error code returned : {:#x}", (u32)*Libraries::Kernel::__Error());
LOG_ERROR(Lib_Net, "error code returned: {}", (u32)*Libraries::Kernel::__Error());
return -1;
}
@@ -124,7 +124,7 @@ int PS4_SYSV_ABI sys_listen(OrbisNetId s, int backlog) {
if (returncode >= 0) {
return returncode;
}
LOG_ERROR(Lib_Net, "error code returned : {:#x}", (u32)*Libraries::Kernel::__Error());
LOG_ERROR(Lib_Net, "error code returned: {}", (u32)*Libraries::Kernel::__Error());
return -1;
}
@@ -140,7 +140,7 @@ int PS4_SYSV_ABI sys_setsockopt(OrbisNetId s, int level, int optname, const void
if (returncode >= 0) {
return returncode;
}
LOG_ERROR(Lib_Net, "error code returned : {:#x}", (u32)*Libraries::Kernel::__Error());
LOG_ERROR(Lib_Net, "error code returned: {}", (u32)*Libraries::Kernel::__Error());
return -1;
}
@@ -204,7 +204,7 @@ int PS4_SYSV_ABI sys_socketclose(OrbisNetId s) {
if (returncode >= 0) {
return returncode;
}
LOG_ERROR(Lib_Net, "error code returned : {:#x}", (u32)*Libraries::Kernel::__Error());
LOG_ERROR(Lib_Net, "error code returned: {}", (u32)*Libraries::Kernel::__Error());
return -1;
}
@@ -220,7 +220,7 @@ int PS4_SYSV_ABI sys_sendto(OrbisNetId s, const void* buf, u64 len, int flags,
if (returncode >= 0) {
return returncode;
}
LOG_ERROR(Lib_Net, "error code returned : {:#x}", (u32)*Libraries::Kernel::__Error());
LOG_ERROR(Lib_Net, "error code returned: {}", (u32)*Libraries::Kernel::__Error());
return -1;
}
@@ -241,7 +241,7 @@ s64 PS4_SYSV_ABI sys_recvfrom(OrbisNetId s, void* buf, u64 len, int flags, Orbis
if (returncode >= 0) {
return returncode;
}
LOG_ERROR(Lib_Net, "error code returned : {:#x}", (u32)*Libraries::Kernel::__Error());
LOG_ERROR(Lib_Net, "error code returned: {}", (u32)*Libraries::Kernel::__Error());
return -1;
}