mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-12 22:10:29 +02:00
sceNetInet: Refactor errno handling and logging, so we always see how it changes
This commit is contained in:
1 parent
e438de1a00
commit
1013be090c
5 files changed
+150
-92
No files matched your search
@@ -330,7 +330,7 @@ static void encode_domain_name(const char *domain, unsigned char *encoded) {
|
||||
const char *start = pos;
|
||||
while (*pos && *pos != '.') pos++;
|
||||
|
||||
*ptr++ = pos - start;
|
||||
*ptr++ = (unsigned char)(pos - start);
|
||||
memcpy(ptr, start, pos - start);
|
||||
ptr += pos - start;
|
||||
|
||||
|
||||
@@ -787,6 +787,9 @@ std::string inetSockoptName2str(int optname, int level) {
|
||||
}
|
||||
|
||||
int convertInetErrnoHost2PSP(int error) {
|
||||
if (error == 0) {
|
||||
return 0;
|
||||
}
|
||||
switch (error) {
|
||||
case EINTR:
|
||||
return ERROR_INET_EINTR;
|
||||
@@ -868,10 +871,54 @@ int convertInetErrnoHost2PSP(int error) {
|
||||
#endif
|
||||
}
|
||||
if (error != 0)
|
||||
return hleLogError(Log::sceNet, error, "Unknown Error Number (%d)", error);
|
||||
return hleLogError(Log::sceNet, error, "Unknown Host Error Number (%d)", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
const char *convertInetErrno2str(int error) {
|
||||
switch (error) {
|
||||
case 0: return "(0=no error)";
|
||||
case ERROR_INET_EINTR: return "EINTR";
|
||||
case ERROR_INET_EBADF: return "EBADF";
|
||||
case ERROR_INET_EACCES: return "EACCES";
|
||||
case ERROR_INET_EFAULT: return "EFAULT";
|
||||
case ERROR_INET_EINVAL: return "EINVAL";
|
||||
case ERROR_INET_ENOSPC: return "ENOSPC";
|
||||
case ERROR_INET_EPIPE: return "EPIPE";
|
||||
case ERROR_INET_ENOMSG: return "ENOMSG";
|
||||
case ERROR_INET_ENOLINK: return "ENOLINK";
|
||||
case ERROR_INET_EPROTO: return "EPROTO";
|
||||
case ERROR_INET_EBADMSG: return "EBADMSG";
|
||||
case ERROR_INET_EOPNOTSUPP: return "EOPNOTSUPP";
|
||||
case ERROR_INET_EPFNOSUPPORT: return "EPFNOSUPPORT";
|
||||
case ERROR_INET_ECONNRESET: return "ECONNRESET";
|
||||
case ERROR_INET_ENOBUFS: return "ENOBUFS";
|
||||
case ERROR_INET_EAFNOSUPPORT: return "EAFNOSUPPORT";
|
||||
case ERROR_INET_EPROTOTYPE: return "EPROTOTYPE";
|
||||
case ERROR_INET_ENOTSOCK: return "ENOTSOCK";
|
||||
case ERROR_INET_ENOPROTOOPT: return "ENOPROTOOPT";
|
||||
case ERROR_INET_ESHUTDOWN: return "ESHUTDOWN";
|
||||
case ERROR_INET_ECONNREFUSED: return "ECONNREFUSED";
|
||||
case ERROR_INET_EADDRINUSE: return "EADDRINUSE";
|
||||
case ERROR_INET_ECONNABORTED: return "ECONNABORTED";
|
||||
case ERROR_INET_ENETUNREACH: return "ENETUNREACH";
|
||||
case ERROR_INET_ENETDOWN: return "ENETDOWN";
|
||||
case ERROR_INET_ETIMEDOUT: return "ETIMEDOUT";
|
||||
case ERROR_INET_EHOSTDOWN: return "EHOSTDOWN";
|
||||
case ERROR_INET_EHOSTUNREACH: return "EHOSTUNREACH";
|
||||
case ERROR_INET_EALREADY: return "EALREADY";
|
||||
case ERROR_INET_EMSGSIZE: return "EMSGSIZE";
|
||||
case ERROR_INET_EPROTONOSUPPORT: return "EPROTONOSUPPORT";
|
||||
case ERROR_INET_ESOCKTNOSUPPORT: return "ESOCKTNOSUPPORT";
|
||||
case ERROR_INET_EADDRNOTAVAIL: return "EADDRNOTAVAIL";
|
||||
case ERROR_INET_ENETRESET: return "ENETRESET";
|
||||
case ERROR_INET_EISCONN: return "EISCONN";
|
||||
case ERROR_INET_ENOTCONN: return "ENOTCONN";
|
||||
case ERROR_INET_EAGAIN: return "EAGAIN";
|
||||
default: return "(unknown!)";
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Some of this might be wrong
|
||||
int convertInetErrno2PSPError(int error) {
|
||||
switch (error) {
|
||||
|
||||
@@ -475,4 +475,5 @@ int convertSockoptNameHost2PSP(int optname, int level);
|
||||
std::string inetSockoptName2str(int optname, int level);
|
||||
int convertInetErrnoHost2PSP(int error);
|
||||
int convertInetErrno2PSPError(int error);
|
||||
const char *convertInetErrno2str(int error);
|
||||
std::string convertNetError2str(uint32_t errorCode);
|
||||
@@ -281,11 +281,6 @@ static void __UpdateApctlHandlers(u32 oldState, u32 newState, u32 flag, u32 erro
|
||||
apctlEvents.push_back({ oldState, newState, flag, error });
|
||||
}
|
||||
|
||||
// Make sure MIPS calls have been fully executed before the next notifyApctlHandlers
|
||||
void notifyApctlHandlers(int oldState, int newState, int flag, int error) {
|
||||
__UpdateApctlHandlers(oldState, newState, flag, error);
|
||||
}
|
||||
|
||||
void netValidateLoopMemory() {
|
||||
// Allocate Memory if it wasn't valid/allocated after loaded from old SaveState
|
||||
if (!apctlThreadHackAddr || (apctlThreadHackAddr && strcmp("apctlThreadHack", kernelMemory.GetBlockTag(apctlThreadHackAddr)) != 0)) {
|
||||
|
||||
+100
-85
@@ -23,7 +23,27 @@
|
||||
#include "Core/Util/PortManager.h"
|
||||
#include "Core/Instance.h"
|
||||
|
||||
int inetLastErrno = 0; // TODO: since errno can only be read once, we should keep track the value to be used on sceNetInetGetErrno
|
||||
// This is the PSP networking errno.
|
||||
// TODO: It should probably be thread-local - one value for each PSP thread?
|
||||
int g_inetLastErrno = 0;
|
||||
|
||||
// Functions should only call this on error, NOT on success.
|
||||
// Returns a PSP errno (ERROR_INET_*), in case it's needed.
|
||||
static int UpdateErrnoFromHost(int hostErrno, const char *func) {
|
||||
int newErrno = convertInetErrnoHost2PSP(hostErrno);
|
||||
if (g_inetLastErrno == 0 && newErrno == 0) {
|
||||
WARN_LOG(Log::sceNet, "BAD: errno set to 0 in %s. Functions should not clear errno.", convertInetErrno2str(g_inetLastErrno), func);
|
||||
} else if (g_inetLastErrno != 0 && newErrno == 0) {
|
||||
ERROR_LOG(Log::sceNet, "BAD: errno cleared (previously %s) in %s. Functions should not clear errno.", convertInetErrno2str(g_inetLastErrno), func);
|
||||
g_inetLastErrno = 0;
|
||||
} else if (g_inetLastErrno == newErrno) {
|
||||
DEBUG_LOG(Log::sceNet, "errno remained %s in %s (host: %d)", convertInetErrno2str(newErrno), func, hostErrno);
|
||||
} else {
|
||||
INFO_LOG(Log::sceNet, "errno set to %s in %s (host: %d)", convertInetErrno2str(newErrno), func, hostErrno);
|
||||
g_inetLastErrno = newErrno;
|
||||
}
|
||||
return g_inetLastErrno;
|
||||
}
|
||||
|
||||
bool netInetInited = false;
|
||||
|
||||
@@ -50,15 +70,12 @@ static int sceNetInetTerm() {
|
||||
}
|
||||
|
||||
static int sceNetInetGetErrno() {
|
||||
int error = convertInetErrnoHost2PSP(inetLastErrno);
|
||||
// We should not reset inetLastErrno to 0 here. This breaks MOHH.
|
||||
return hleLogSuccessInfoI(Log::sceNet, error, "at %08x", currentMIPS->pc);
|
||||
return hleLogSuccessInfoI(Log::sceNet, g_inetLastErrno, "returning %s at %08x", convertInetErrno2str(g_inetLastErrno), currentMIPS->pc);
|
||||
}
|
||||
|
||||
static int sceNetInetGetPspError() {
|
||||
int error = convertInetErrno2PSPError(convertInetErrnoHost2PSP(inetLastErrno));
|
||||
// We should not reset inetLastErrno to 0 here.
|
||||
return hleLogSuccessInfoI(Log::sceNet, error, "at %08x", currentMIPS->pc);
|
||||
uint32_t error = convertInetErrno2PSPError(g_inetLastErrno);
|
||||
return hleLogSuccessInfoI(Log::sceNet, error, "returning %s converted to %08x at %08x", convertInetErrno2str(g_inetLastErrno), error, currentMIPS->pc);
|
||||
}
|
||||
|
||||
static int sceNetInetInetPton(int af, const char* hostname, u32 inAddrPtr) {
|
||||
@@ -67,6 +84,11 @@ static int sceNetInetInetPton(int af, const char* hostname, u32 inAddrPtr) {
|
||||
}
|
||||
|
||||
int retval = inet_pton(convertSocketDomainPSP2Host(af), hostname, (void*)Memory::GetPointer(inAddrPtr));
|
||||
// Note that inet_pton can set errno!
|
||||
if (retval < 0) {
|
||||
UpdateErrnoFromHost(socket_errno, __FUNCTION__);
|
||||
return hleLogError(Log::sceNet, retval);
|
||||
}
|
||||
return hleLogSuccessI(Log::sceNet, retval);
|
||||
}
|
||||
|
||||
@@ -75,6 +97,7 @@ static int sceNetInetInetAton(const char* hostname, u32 inAddrPtr) {
|
||||
return hleLogError(Log::sceNet, 0, "invalid arg"); //-1
|
||||
}
|
||||
|
||||
// TODO: Wait what, we're calling pton in aton?
|
||||
int retval = inet_pton(AF_INET, hostname, (void*)Memory::GetPointer(inAddrPtr));
|
||||
// inet_aton() returns nonzero if the address is valid, zero if not.
|
||||
return hleLogSuccessI(Log::sceNet, retval);
|
||||
@@ -87,7 +110,7 @@ static u32 sceNetInetInetNtop(int af, u32 srcInAddrPtr, u32 dstBufPtr, u32 bufsi
|
||||
return hleLogError(Log::sceNet, 0, "invalid arg");
|
||||
}
|
||||
if (!Memory::IsValidAddress(dstBufPtr) || bufsize < 1/*8*/) { // usually 8 or 16, but Coded Arms Contagion is using bufsize = 4
|
||||
inetLastErrno = ENOSPC;
|
||||
UpdateErrnoFromHost(ENOSPC, __FUNCTION__);
|
||||
return hleLogError(Log::sceNet, 0, "invalid arg");
|
||||
}
|
||||
|
||||
@@ -110,7 +133,7 @@ static u32_le sceNetInetInetAddr(const char *hostname) {
|
||||
|
||||
static int sceNetInetGetpeername(int socket, u32 namePtr, u32 namelenPtr) {
|
||||
if (!Memory::IsValidAddress(namePtr) || !Memory::IsValidAddress(namelenPtr)) {
|
||||
inetLastErrno = EFAULT;
|
||||
UpdateErrnoFromHost(EFAULT, __FUNCTION__);
|
||||
return hleLogError(Log::sceNet, -1, "invalid arg");
|
||||
}
|
||||
|
||||
@@ -132,8 +155,8 @@ static int sceNetInetGetpeername(int socket, u32 namePtr, u32 namelenPtr) {
|
||||
DEBUG_LOG(Log::sceNet, "Getpeername: Family = %s, Address = %s, Port = %d", inetSocketDomain2str(saddr.addr.sa_family).c_str(), ip2str(saddr.in.sin_addr).c_str(), ntohs(saddr.in.sin_port));
|
||||
*namelen = len;
|
||||
if (retval < 0) {
|
||||
inetLastErrno = socket_errno;
|
||||
return hleLogError(Log::sceNet, retval, "errno = %d", inetLastErrno);
|
||||
UpdateErrnoFromHost(socket_errno, __FUNCTION__);
|
||||
return hleLogError(Log::sceNet, retval);
|
||||
}
|
||||
|
||||
// We shouldn't use the returned len here, because the returned len is the actual size needed, which can be larger than the inputted len
|
||||
@@ -144,7 +167,7 @@ static int sceNetInetGetpeername(int socket, u32 namePtr, u32 namelenPtr) {
|
||||
|
||||
static int sceNetInetGetsockname(int socket, u32 namePtr, u32 namelenPtr) {
|
||||
if (!Memory::IsValidAddress(namePtr) || !Memory::IsValidAddress(namelenPtr)) {
|
||||
inetLastErrno = EFAULT;
|
||||
UpdateErrnoFromHost(EFAULT, __FUNCTION__);
|
||||
return hleLogError(Log::sceNet, -1, "invalid arg");
|
||||
}
|
||||
|
||||
@@ -165,8 +188,8 @@ static int sceNetInetGetsockname(int socket, u32 namePtr, u32 namelenPtr) {
|
||||
DEBUG_LOG(Log::sceNet, "Getsockname: Family = %s, Address = %s, Port = %d", inetSocketDomain2str(saddr.addr.sa_family).c_str(), ip2str(saddr.in.sin_addr).c_str(), ntohs(saddr.in.sin_port));
|
||||
*namelen = len;
|
||||
if (retval < 0) {
|
||||
inetLastErrno = socket_errno;
|
||||
return hleLogError(Log::sceNet, retval, "errno = %d", inetLastErrno);
|
||||
UpdateErrnoFromHost(socket_errno, __FUNCTION__);
|
||||
return hleLogError(Log::sceNet, retval);
|
||||
}
|
||||
|
||||
// We shouldn't use the returned len here, because the returned len is the actual size needed, which can be larger than the inputted len
|
||||
@@ -289,11 +312,7 @@ int sceNetInetSelect(int nfds, u32 readfdsPtr, u32 writefdsPtr, u32 exceptfdsPtr
|
||||
}
|
||||
|
||||
if (retval < 0) {
|
||||
inetLastErrno = socket_errno;
|
||||
if (inetLastErrno == 0)
|
||||
hleLogDebug(Log::sceNet, retval, "errno = %d", inetLastErrno);
|
||||
else if (inetLastErrno < 0)
|
||||
hleLogError(Log::sceNet, retval, "errno = %d", inetLastErrno);
|
||||
UpdateErrnoFromHost(socket_errno, __FUNCTION__);
|
||||
return hleLogDebug(Log::sceNet, hleDelayResult(retval, "workaround until blocking-socket", 500)); // Using hleDelayResult as a workaround for games that need blocking-socket to be implemented (ie. Coded Arms Contagion)
|
||||
}
|
||||
return hleLogSuccessI(Log::sceNet, hleDelayResult(retval, "workaround until blocking-socket", 500)); // Using hleDelayResult as a workaround for games that need blocking-socket to be implemented (ie. Coded Arms Contagion)
|
||||
@@ -313,7 +332,7 @@ int sceNetInetPoll(u32 fdsPtr, u32 nfds, int timeout) { // timeout in milisecond
|
||||
for (int i = 0; i < (s32)nfds; i++) {
|
||||
if (fdarray[i].fd < 0) {
|
||||
// In Unix, this is OK and means it the fd should be ignored, except fdarray[i].revents should be zeroed.
|
||||
inetLastErrno = EINVAL;
|
||||
UpdateErrnoFromHost(EINVAL, __FUNCTION__);
|
||||
return hleLogError(Log::sceNet, -1, "invalid socket id");
|
||||
}
|
||||
SOCKET hostSocket = g_socketManager.GetHostSocketFromInetSocket(fdarray[i].fd);
|
||||
@@ -335,7 +354,7 @@ int sceNetInetPoll(u32 fdsPtr, u32 nfds, int timeout) { // timeout in milisecond
|
||||
// TODO: Simulate blocking behaviour when timeout is non-zero to prevent PPSSPP from freezing
|
||||
retval = select(maxHostFd + 1, &readfds, &writefds, &exceptfds, /*(timeout<0)? NULL:*/&tmout);
|
||||
if (retval < 0) {
|
||||
inetLastErrno = EINTR;
|
||||
UpdateErrnoFromHost(EINTR, __FUNCTION__);
|
||||
return hleLogError(Log::sceNet, hleDelayResult(retval, "workaround until blocking-socket", 500)); // Using hleDelayResult as a workaround for games that need blocking-socket to be implemented
|
||||
}
|
||||
|
||||
@@ -367,12 +386,12 @@ static int sceNetInetRecv(int socket, u32 bufPtr, u32 bufLen, u32 flags) {
|
||||
flgs = convertMSGFlagsPSP2Host(flgs);
|
||||
int retval = recv(inetSock->sock, (char*)Memory::GetPointer(bufPtr), bufLen, flgs | MSG_NOSIGNAL);
|
||||
if (retval < 0) {
|
||||
inetLastErrno = socket_errno;
|
||||
if (inetLastErrno == EAGAIN)
|
||||
hleLogDebug(Log::sceNet, retval, "errno = %d", inetLastErrno);
|
||||
else
|
||||
hleLogError(Log::sceNet, retval, "errno = %d", inetLastErrno);
|
||||
return hleDelayResult(retval, "workaround until blocking-socket", 500); // Using hleDelayResult as a workaround for games that need blocking-socket to be implemented
|
||||
if (UpdateErrnoFromHost(socket_errno, __FUNCTION__) == ERROR_INET_EAGAIN) {
|
||||
hleLogDebug(Log::sceNet, retval, "EAGAIN");
|
||||
} else {
|
||||
hleLogError(Log::sceNet, retval);
|
||||
}
|
||||
return hleDelayResult(retval, "workaround until blocking-socket", 500);
|
||||
}
|
||||
|
||||
std::string datahex;
|
||||
@@ -395,14 +414,9 @@ static int sceNetInetSend(int socket, u32 bufPtr, u32 bufLen, u32 flags) {
|
||||
int flgs = flags & ~PSP_NET_INET_MSG_DONTWAIT; // removing non-POSIX flag, which is an alternative way to use non-blocking mode
|
||||
flgs = convertMSGFlagsPSP2Host(flgs);
|
||||
int retval = send(inetSock->sock, (char*)Memory::GetPointer(bufPtr), bufLen, flgs | MSG_NOSIGNAL);
|
||||
|
||||
if (retval < 0) {
|
||||
inetLastErrno = socket_errno;
|
||||
if (inetLastErrno == EAGAIN) {
|
||||
return hleLogDebug(Log::sceNet, retval, "errno = %d", inetLastErrno);
|
||||
} else {
|
||||
return hleLogError(Log::sceNet, retval, "errno = %d", inetLastErrno);
|
||||
}
|
||||
UpdateErrnoFromHost(socket_errno, __FUNCTION__);
|
||||
return hleLogError(Log::sceNet, retval);
|
||||
}
|
||||
return hleLogSuccessInfoI(Log::sceNet, retval);
|
||||
}
|
||||
@@ -413,9 +427,11 @@ static int sceNetInetSocket(int domain, int type, int protocol) {
|
||||
domain, type, protocol, currentMIPS->pc, inetSocketDomain2str(domain).c_str(), inetSocketType2str(type).c_str(), inetSocketProto2str(protocol).c_str());
|
||||
|
||||
int socket;
|
||||
InetSocket *inetSock = g_socketManager.CreateSocket(&socket, &inetLastErrno, SocketState::UsedNetInet, domain, type, protocol);
|
||||
int hostErrno = 0;
|
||||
InetSocket *inetSock = g_socketManager.CreateSocket(&socket, &hostErrno, SocketState::UsedNetInet, domain, type, protocol);
|
||||
if (!inetSock) {
|
||||
return hleLogError(Log::sceNet, -1, "errno = %d", inetLastErrno);
|
||||
UpdateErrnoFromHost(hostErrno, __FUNCTION__);
|
||||
return hleLogError(Log::sceNet, -1);
|
||||
}
|
||||
|
||||
// Ignore SIGPIPE when supported (ie. BSD/MacOS)
|
||||
@@ -435,17 +451,15 @@ static int sceNetInetSetsockopt(int socket, int level, int optname, u32 optvalPt
|
||||
return hleLogError(Log::sceNet, ERROR_INET_EBADF, "Bad socket #%d", socket);
|
||||
}
|
||||
|
||||
u32_le* optval = (u32_le*)Memory::GetPointer(optvalPtr);
|
||||
u32 optval = optvalPtr ? Memory::Read_U32(optvalPtr) : 0;
|
||||
WARN_LOG(Log::sceNet, "sceNetInetSetsockopt(%i, %i, %i, %08x, %i) at %08x: Level = %s, OptName = %s, OptValue = %d",
|
||||
socket, level, optname, optvalPtr, optlen, currentMIPS->pc,
|
||||
inetSockoptLevel2str(level).c_str(), inetSockoptName2str(optname, level).c_str(), optval ? *optval : 0);
|
||||
inetSockoptLevel2str(level).c_str(), inetSockoptName2str(optname, level).c_str(), optval);
|
||||
|
||||
timeval tval{};
|
||||
// TODO: Ignoring SO_NBIO/SO_NONBLOCK flag if we always use non-blocking mode (ie. simulated blocking mode)
|
||||
if (level == PSP_NET_INET_SOL_SOCKET && optname == PSP_NET_INET_SO_NBIO) {
|
||||
int nonblocking;
|
||||
memcpy(&nonblocking, (int*)optval, sizeof(int));
|
||||
inetSock->nonblocking = nonblocking;
|
||||
inetSock->nonblocking = optval;
|
||||
return hleLogSuccessI(Log::sceNet, 0);
|
||||
}
|
||||
// FIXME: Should we ignore SO_BROADCAST flag since we are using fake broadcast (ie. only broadcast to friends),
|
||||
@@ -472,23 +486,23 @@ static int sceNetInetSetsockopt(int socket, int level, int optname, u32 optvalPt
|
||||
// It seems UNO game will try to set socket buffer size with a very large size and ended getting error (-1), so we should also limit the buffer size to replicate PSP behavior
|
||||
else if (level == PSP_NET_INET_SOL_SOCKET && (optname == PSP_NET_INET_SO_RCVBUF || optname == PSP_NET_INET_SO_SNDBUF)) { // PSP_NET_INET_SO_NOSIGPIPE ?
|
||||
// TODO: For SOCK_STREAM max buffer size is 8 Mb on BSD, while max SOCK_DGRAM is 65535 minus the IP & UDP Header size
|
||||
if (*optval > 8 * 1024 * 1024) {
|
||||
inetLastErrno = ENOBUFS; // FIXME: return ENOBUFS for SOCK_STREAM, and EINVAL for SOCK_DGRAM
|
||||
if (optval > 8 * 1024 * 1024) {
|
||||
UpdateErrnoFromHost(ENOBUFS, __FUNCTION__); // FIXME: return ENOBUFS for SOCK_STREAM, and EINVAL for SOCK_DGRAM
|
||||
return hleLogError(Log::sceNet, -1, "buffer size too large?");
|
||||
}
|
||||
}
|
||||
int retval = 0;
|
||||
// PSP timeout are a single 32bit value (micro seconds)
|
||||
if (level == PSP_NET_INET_SOL_SOCKET && optval && (optname == PSP_NET_INET_SO_RCVTIMEO || optname == PSP_NET_INET_SO_SNDTIMEO)) {
|
||||
tval.tv_sec = *optval / 1000000; // seconds
|
||||
tval.tv_usec = (*optval % 1000000); // microseconds
|
||||
tval.tv_sec = optval / 1000000; // seconds
|
||||
tval.tv_usec = (optval % 1000000); // microseconds
|
||||
retval = setsockopt(inetSock->sock, convertSockoptLevelPSP2Host(level), convertSockoptNamePSP2Host(optname, level), (char*)&tval, sizeof(tval));
|
||||
} else {
|
||||
retval = setsockopt(inetSock->sock, convertSockoptLevelPSP2Host(level), convertSockoptNamePSP2Host(optname, level), (char*)optval, optlen);
|
||||
retval = setsockopt(inetSock->sock, convertSockoptLevelPSP2Host(level), convertSockoptNamePSP2Host(optname, level), (char*)&optval, optlen);
|
||||
}
|
||||
if (retval < 0) {
|
||||
inetLastErrno = socket_errno;
|
||||
hleLogError(Log::sceNet, retval, "errno = %d", inetLastErrno);
|
||||
UpdateErrnoFromHost(socket_errno, __FUNCTION__);
|
||||
hleLogError(Log::sceNet, retval);
|
||||
}
|
||||
return hleLogSuccessI(Log::sceNet, retval);
|
||||
}
|
||||
@@ -551,8 +565,8 @@ static int sceNetInetGetsockopt(int socket, int level, int optname, u32 optvalPt
|
||||
retval = getsockopt(inetSock->sock, convertSockoptLevelPSP2Host(level), convertSockoptNamePSP2Host(optname, level), (char*)optval, optlen);
|
||||
}
|
||||
if (retval < 0) {
|
||||
inetLastErrno = socket_errno;
|
||||
hleLogError(Log::sceNet, retval, "errno = %d", inetLastErrno);
|
||||
UpdateErrnoFromHost(socket_errno, __FUNCTION__);
|
||||
hleLogError(Log::sceNet, retval);
|
||||
}
|
||||
DEBUG_LOG(Log::sceNet, "SockOpt: OptValue = %d", *optval);
|
||||
return hleLogSuccessI(Log::sceNet, retval);
|
||||
@@ -593,9 +607,9 @@ static int sceNetInetBind(int socket, u32 namePtr, int namelen) {
|
||||
changeBlockingMode(inetSock->sock, 0);
|
||||
int retval = bind(inetSock->sock, (struct sockaddr*)&saddr, len);
|
||||
if (retval < 0) {
|
||||
inetLastErrno = socket_errno;
|
||||
UpdateErrnoFromHost(socket_errno, __FUNCTION__);
|
||||
changeBlockingMode(inetSock->sock, 1);
|
||||
return hleLogError(Log::sceNet, retval, "errno = %d", inetLastErrno);
|
||||
return hleLogError(Log::sceNet, retval);
|
||||
}
|
||||
changeBlockingMode(inetSock->sock, 1);
|
||||
// Update binded port number if it was 0 (any port)
|
||||
@@ -615,13 +629,14 @@ static int sceNetInetBind(int socket, u32 namePtr, int namelen) {
|
||||
}
|
||||
|
||||
static int sceNetInetConnect(int socket, u32 sockAddrPtr, int sockAddrLen) {
|
||||
WARN_LOG(Log::sceNet, " %s(%i, %08x, %i) at %08x", __FUNCTION__, socket, sockAddrPtr, sockAddrLen, currentMIPS->pc);
|
||||
|
||||
InetSocket *inetSock;
|
||||
if (!g_socketManager.GetInetSocket(socket, &inetSock)) {
|
||||
return hleLogError(Log::sceNet, ERROR_INET_EBADF, "Bad socket #%d", socket);
|
||||
}
|
||||
|
||||
// Still using warn log here so it stands out in the log
|
||||
WARN_LOG(Log::sceNet, "sceNetInetConnect(%i, %08x, %i) at %08x", socket, sockAddrPtr, sockAddrLen, currentMIPS->pc);
|
||||
|
||||
SceNetInetSockaddr* dst = (SceNetInetSockaddr*)Memory::GetPointer(sockAddrPtr);
|
||||
SockAddrIN4 saddr{};
|
||||
int dstlen = std::min(sockAddrLen > 0 ? sockAddrLen : 0, static_cast<int>(sizeof(saddr)));
|
||||
@@ -634,11 +649,12 @@ static int sceNetInetConnect(int socket, u32 sockAddrPtr, int sockAddrLen) {
|
||||
changeBlockingMode(inetSock->sock, 0); // Use blocking mode as temporary fix for UNO, since we don't simulate blocking-mode yet
|
||||
int retval = connect(inetSock->sock, (struct sockaddr*)&saddr.addr, dstlen);
|
||||
if (retval < 0) {
|
||||
inetLastErrno = socket_errno;
|
||||
if (connectInProgress(inetLastErrno))
|
||||
hleLogDebug(Log::sceNet, retval, "errno = %d Address = %s, Port = %d", inetLastErrno, ip2str(saddr.in.sin_addr).c_str(), ntohs(saddr.in.sin_port));
|
||||
int hostErrno = socket_errno;
|
||||
UpdateErrnoFromHost(hostErrno, __FUNCTION__);
|
||||
if (connectInProgress(hostErrno))
|
||||
hleLogDebug(Log::sceNet, retval, "errno = %s Address = %s, Port = %d", convertInetErrno2str(g_inetLastErrno), ip2str(saddr.in.sin_addr).c_str(), ntohs(saddr.in.sin_port));
|
||||
else
|
||||
hleLogError(Log::sceNet, retval, "errno = %d Address = %s, Port = %d", inetLastErrno, ip2str(saddr.in.sin_addr).c_str(), ntohs(saddr.in.sin_port));
|
||||
hleLogError(Log::sceNet, retval, "errno = %s Address = %s, Port = %d", convertInetErrno2str(g_inetLastErrno), ip2str(saddr.in.sin_addr).c_str(), ntohs(saddr.in.sin_port));
|
||||
changeBlockingMode(inetSock->sock, 1);
|
||||
// TODO: Since we're temporarily forcing blocking-mode we'll need to change errno from ETIMEDOUT to EAGAIN
|
||||
/*if (inetLastErrno == ETIMEDOUT)
|
||||
@@ -659,8 +675,8 @@ static int sceNetInetListen(int socket, int backlog) {
|
||||
|
||||
int retval = listen(inetSock->sock, (backlog == PSP_NET_INET_SOMAXCONN ? SOMAXCONN : backlog));
|
||||
if (retval < 0) {
|
||||
inetLastErrno = socket_errno;
|
||||
return hleLogError(Log::sceNet, retval, "errno = %d", inetLastErrno);
|
||||
UpdateErrnoFromHost(socket_errno, __FUNCTION__);
|
||||
return hleLogError(Log::sceNet, retval);
|
||||
}
|
||||
|
||||
return hleLogSuccessInfoI(Log::sceNet, retval);
|
||||
@@ -680,11 +696,11 @@ static int sceNetInetAccept(int socket, u32 addrPtr, u32 addrLenPtr) {
|
||||
|
||||
int newHostSocket = accept(inetSock->sock, (struct sockaddr*)&saddr.addr, srclen);
|
||||
if (newHostSocket < 0) {
|
||||
inetLastErrno = socket_errno;
|
||||
if (inetLastErrno == EAGAIN)
|
||||
hleLogDebug(Log::sceNet, newHostSocket, "errno = %d", inetLastErrno);
|
||||
else
|
||||
hleLogError(Log::sceNet, newHostSocket, "errno = %d", inetLastErrno);
|
||||
if (UpdateErrnoFromHost(socket_errno, __FUNCTION__) == ERROR_INET_EAGAIN) {
|
||||
hleLogDebug(Log::sceNet, newHostSocket, "EAGAIN");
|
||||
} else {
|
||||
hleLogError(Log::sceNet, newHostSocket);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -692,7 +708,7 @@ static int sceNetInetAccept(int socket, u32 addrPtr, u32 addrLenPtr) {
|
||||
InetSocket *newInetSocket = g_socketManager.AdoptSocket(&newSocketId, newHostSocket, inetSock);
|
||||
if (!newInetSocket) {
|
||||
// Ran out of space. Shouldn't really happen.
|
||||
inetLastErrno = ENOMEM;
|
||||
UpdateErrnoFromHost(ENOMEM, __FUNCTION__);
|
||||
return hleLogError(Log::sceNet, -1, "Out of socket IDs");;
|
||||
}
|
||||
|
||||
@@ -777,11 +793,10 @@ static int sceNetInetRecvfrom(int socket, u32 bufferPtr, int len, int flags, u32
|
||||
flgs = convertMSGFlagsPSP2Host(flgs);
|
||||
int retval = recvfrom(inetSock->sock, (char*)Memory::GetPointer(bufferPtr), len, flgs | MSG_NOSIGNAL, (struct sockaddr*)&saddr.addr, srclen);
|
||||
if (retval < 0) {
|
||||
inetLastErrno = socket_errno;
|
||||
if (inetLastErrno == EAGAIN) {
|
||||
hleLogDebug(Log::sceNet, retval, "errno = %d", inetLastErrno);
|
||||
if (UpdateErrnoFromHost(socket_errno, __FUNCTION__) == ERROR_INET_EAGAIN) {
|
||||
hleLogDebug(Log::sceNet, retval, "EAGAIN");
|
||||
} else {
|
||||
hleLogError(Log::sceNet, retval, "errno = %d", inetLastErrno);
|
||||
hleLogError(Log::sceNet, retval);
|
||||
}
|
||||
// Using hleDelayResult as a workaround for games that need blocking-socket to be implemented (ie. Coded Arms Contagion)
|
||||
return hleDelayResult(retval, "workaround until blocking-socket", 500);
|
||||
@@ -873,11 +888,11 @@ static int sceNetInetSendto(int socket, u32 bufferPtr, int len, int flags, u32 t
|
||||
retval = sendto(inetSock->sock, (char*)Memory::GetPointer(bufferPtr), len, flgs | MSG_NOSIGNAL, (struct sockaddr*)&saddr.addr, dstlen);
|
||||
}
|
||||
if (retval < 0) {
|
||||
inetLastErrno = socket_errno;
|
||||
if (inetLastErrno == EAGAIN)
|
||||
hleLogDebug(Log::sceNet, retval, "errno = %d", inetLastErrno);
|
||||
else
|
||||
hleLogError(Log::sceNet, retval, "errno = %d", inetLastErrno);
|
||||
if (UpdateErrnoFromHost(socket_errno, __FUNCTION__) == ERROR_INET_EAGAIN) {
|
||||
hleLogDebug(Log::sceNet, retval, "EAGAIN");
|
||||
} else {
|
||||
hleLogError(Log::sceNet, retval);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
@@ -891,7 +906,7 @@ static int sceNetInetSendmsg(int socket, u32 msghdrPtr, int flags) {
|
||||
// Note: sendmsg is concatenating iovec buffers before sending it, and send/sendto is just a wrapper for sendmsg according to https://stackoverflow.com/questions/4258834/how-sendmsg-works
|
||||
int retval = -1;
|
||||
if (!Memory::IsValidAddress(msghdrPtr)) {
|
||||
inetLastErrno = EFAULT;
|
||||
UpdateErrnoFromHost(EFAULT, __FUNCTION__);
|
||||
return hleLogError(Log::sceNet, retval);
|
||||
}
|
||||
|
||||
@@ -916,7 +931,7 @@ static int sceNetInetSendmsg(int socket, u32 msghdrPtr, int flags) {
|
||||
iovec* iov = (iovec*)malloc(pspMsghdr->msg_iovlen * iovecsize);
|
||||
#endif
|
||||
if (iov == NULL) {
|
||||
inetLastErrno = ENOBUFS;
|
||||
UpdateErrnoFromHost(ENOBUFS, __FUNCTION__);
|
||||
return hleLogError(Log::sceNet, retval);
|
||||
}
|
||||
memset(iov, 0, pspMsghdr->msg_iovlen * iovecsize);
|
||||
@@ -964,7 +979,7 @@ static int sceNetInetSendmsg(int socket, u32 msghdrPtr, int flags) {
|
||||
chdr = (cmsghdr*)malloc(pspMsghdr->msg_controllen);
|
||||
#endif
|
||||
if (chdr == NULL) {
|
||||
inetLastErrno = ENOBUFS;
|
||||
UpdateErrnoFromHost(ENOBUFS, __FUNCTION__);
|
||||
free(iov);
|
||||
return hleLogError(Log::sceNet, retval);
|
||||
}
|
||||
@@ -1074,11 +1089,11 @@ static int sceNetInetSendmsg(int socket, u32 msghdrPtr, int flags) {
|
||||
free(buf);
|
||||
*/
|
||||
if (retval < 0) {
|
||||
inetLastErrno = socket_errno;
|
||||
if (inetLastErrno == EAGAIN)
|
||||
hleLogDebug(Log::sceNet, retval, "errno = %d", inetLastErrno);
|
||||
else
|
||||
hleLogError(Log::sceNet, retval, "errno = %d", inetLastErrno);
|
||||
if (UpdateErrnoFromHost(socket_errno, __FUNCTION__) == ERROR_INET_EAGAIN) {
|
||||
hleLogDebug(Log::sceNet, retval, "EAGAIN");
|
||||
} else {
|
||||
hleLogError(Log::sceNet, retval);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
return hleLogSuccessInfoI(Log::sceNet, retval); // returns number of bytes sent?
|
||||
@@ -1097,7 +1112,7 @@ static int sceNetInetRecvmsg(int socket, u32 msghdrPtr, int flags) {
|
||||
// Reference: http://www.masterraghu.com/subjects/np/introduction/unix_network_programming_v1.3/ch14lev1sec5.html
|
||||
int retval = -1;
|
||||
if (!Memory::IsValidAddress(msghdrPtr)) {
|
||||
inetLastErrno = EFAULT;
|
||||
UpdateErrnoFromHost(EFAULT, __FUNCTION__);
|
||||
return hleLogError(Log::sceNet, retval);
|
||||
}
|
||||
InetMsghdr* pspMsghdr = (InetMsghdr*)Memory::GetPointer(msghdrPtr);
|
||||
@@ -1116,7 +1131,7 @@ static int sceNetInetRecvmsg(int socket, u32 msghdrPtr, int flags) {
|
||||
iovec* iov = (iovec*)malloc(pspMsghdr->msg_iovlen * iovecsize);
|
||||
#endif
|
||||
if (iov == NULL) {
|
||||
inetLastErrno = ENOBUFS;
|
||||
UpdateErrnoFromHost(ENOBUFS, __FUNCTION__);
|
||||
return hleLogError(Log::sceNet, retval);
|
||||
}
|
||||
memset(iov, 0, pspMsghdr->msg_iovlen * iovecsize);
|
||||
|
||||
Reference in new issue
Block a user