mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-12-09 13:19:00 +00:00
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:
committed by
GitHub
parent
074dfe2571
commit
2f701311f2
@@ -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() {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user