diff --git a/Core/HLE/proAdhoc.cpp b/Core/HLE/proAdhoc.cpp index 6eb2891026..879202d855 100644 --- a/Core/HLE/proAdhoc.cpp +++ b/Core/HLE/proAdhoc.cpp @@ -298,8 +298,11 @@ int IsSocketReady(int fd, bool readfd, bool writefd, int* errorcode, int timeout timeval tval; // Avoid getting Fatal signal 6 (SIGABRT) on linux/android - if (fd < 0) - return SOCKET_ERROR; + if (fd < 0) { + if (errorcode != nullptr) + *errorcode = EBADF; + return SOCKET_ERROR; + } FD_ZERO(&readfds); writefds = readfds; @@ -312,9 +315,10 @@ int IsSocketReady(int fd, bool readfd, bool writefd, int* errorcode, int timeout tval.tv_sec = timeoutUS / 1000000; tval.tv_usec = timeoutUS % 1000000; + // Note: select will flags an unconnected TCP socket (ie. a freshly created socket without connecting first, or when connect failed with ECONNREFUSED on linux) as writeable/readable, thus can't be used to tell whether the connection has established or not. int ret = select(fd + 1, readfd? &readfds: nullptr, writefd? &writefds: nullptr, nullptr, &tval); if (errorcode != nullptr) - *errorcode = errno; + *errorcode = (ret < 0? errno: 0); return ret; } diff --git a/Core/HLE/proAdhoc.h b/Core/HLE/proAdhoc.h index 2e44d893cb..c352fb2b8f 100644 --- a/Core/HLE/proAdhoc.h +++ b/Core/HLE/proAdhoc.h @@ -63,6 +63,7 @@ #undef ECONNREFUSED #undef ENETUNREACH #undef ENOTCONN +#undef EBADF #undef EAGAIN #undef EINPROGRESS #undef EISCONN @@ -76,6 +77,7 @@ #define ECONNREFUSED WSAECONNREFUSED #define ENETUNREACH WSAENETUNREACH #define ENOTCONN WSAENOTCONN +#define EBADF WSAEBADF #define EAGAIN WSAEWOULDBLOCK #define EINPROGRESS WSAEWOULDBLOCK #define EISCONN WSAEISCONN diff --git a/Core/HLE/sceNetAdhoc.cpp b/Core/HLE/sceNetAdhoc.cpp index 6b5584678c..5fbf285751 100644 --- a/Core/HLE/sceNetAdhoc.cpp +++ b/Core/HLE/sceNetAdhoc.cpp @@ -831,6 +831,21 @@ int DoBlockingPtpConnect(AdhocSocketRequest& req, s64& result, AdhocSendTargets& if (RecreatePtpSocket(req.id) < 0) { WARN_LOG(SCENET, "sceNetAdhocPtpConnect[%i:%u]: Failed to Recreate Socket", req.id, ptpsocket.lport); } + + u64 now = (u64)(time_now_d() * 1000000.0); + if (req.timeout == 0 || now - req.startTime <= req.timeout) { + // Try again later + return -1; + } + else { + // Handle Workaround that force the first Connect to be blocking for issue related to lobby or high latency networks + if (sock->nonblocking) + result = ERROR_NET_ADHOC_WOULD_BLOCK; + else + result = ERROR_NET_ADHOC_TIMEOUT; // FIXME: PSP never returned ERROR_NET_ADHOC_TIMEOUT on PtpConnect? or only returned ERROR_NET_ADHOC_TIMEOUT when the host is too busy? Seems to be returning ERROR_NET_ADHOC_CONNECTION_REFUSED on timedout instead (if the other side in not listening yet, which is similar to BSD). + + return 0; + } } } // Check if the connection has completed (assuming "connect" has been called before)