From d23e1c09498b33666e7e88308155c2f4e2d05c47 Mon Sep 17 00:00:00 2001 From: ANR2ME Date: Sat, 13 Feb 2021 21:53:52 +0700 Subject: [PATCH 1/6] Shows a warning log when bound port is shifted to negative port (may cause port issue when wrapped to 1024 or lower on android) --- Core/HLE/sceNetAdhoc.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Core/HLE/sceNetAdhoc.cpp b/Core/HLE/sceNetAdhoc.cpp index a14eafed6e..f0a8297962 100644 --- a/Core/HLE/sceNetAdhoc.cpp +++ b/Core/HLE/sceNetAdhoc.cpp @@ -1259,6 +1259,8 @@ static int sceNetAdhocPdpCreate(const char *mac, int port, int bufferSize, u32 f // Update sport with the port assigned internal->lport = ntohs(local.sin_port) socklen_t len = sizeof(addr); if (getsockname(usocket, (sockaddr*)&addr, &len) == 0) { + if (port + static_cast(portOffset) > 65535 || static_cast(ntohs(addr.sin_port)) - static_cast(portOffset) <= 0) + WARN_LOG(SCENET, "sceNetAdhocPdpCreate - Shifting to Negative Port: %d -> %d -> %d", port, port + portOffset, ntohs(addr.sin_port) - portOffset); port = ntohs(addr.sin_port) - portOffset; } @@ -3155,6 +3157,8 @@ static int sceNetAdhocPtpOpen(const char *srcmac, int sport, const char *dstmac, // Update sport with the port assigned internal->lport = ntohs(local.sin_port) socklen_t len = sizeof(addr); if (getsockname(tcpsocket, (sockaddr*)&addr, &len) == 0) { + if (sport + static_cast(portOffset) > 65535 || static_cast(ntohs(addr.sin_port)) - static_cast(portOffset) <= 0) + WARN_LOG(SCENET, "sceNetAdhocPtpOpen - Shifting to Negative Port: %d -> %d -> %d", sport, sport + portOffset, ntohs(addr.sin_port) - portOffset); sport = ntohs(addr.sin_port) - portOffset; } @@ -3718,6 +3722,8 @@ static int sceNetAdhocPtpListen(const char *srcmac, int sport, int bufsize, int // Update sport with the port assigned internal->lport = ntohs(local.sin_port) socklen_t len = sizeof(addr); if (getsockname(tcpsocket, (sockaddr*)&addr, &len) == 0) { + if (sport + static_cast(portOffset) > 65535 || static_cast(ntohs(addr.sin_port)) - static_cast(portOffset) <= 0) + WARN_LOG(SCENET, "sceNetAdhocPtpListen - Shifting to Negative Port: %d -> %d -> %d", sport, sport + portOffset, ntohs(addr.sin_port) - portOffset); sport = ntohs(addr.sin_port) - portOffset; } // Switch into Listening Mode From eef3110dcf93251930bfd0964caa348cd5a922ba Mon Sep 17 00:00:00 2001 From: ANR2ME Date: Sat, 13 Feb 2021 21:17:59 +0700 Subject: [PATCH 2/6] Shows a warning on Screen when detecting AdhocMatching data coming from an incorrect port, progressing any further may ended with connection issue. Players will need to wait until the port detected correctly before progressing any further (may takes a few more seconds) --- Core/HLE/sceNetAdhoc.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Core/HLE/sceNetAdhoc.cpp b/Core/HLE/sceNetAdhoc.cpp index f0a8297962..8dca3921bd 100644 --- a/Core/HLE/sceNetAdhoc.cpp +++ b/Core/HLE/sceNetAdhoc.cpp @@ -7072,6 +7072,7 @@ int matchingEventThread(int matchingId) int matchingInputThread(int matchingId) // TODO: The MatchingInput thread is using sceNetAdhocPdpRecv & sceNetAdhocPdpSend functions so it might be better to run this on PSP thread instead of real thread { setCurrentThreadName("MatchingInput"); + auto n = GetI18NCategory("Networking"); // Multithreading Lock peerlock.lock(); // Cast Context @@ -7247,6 +7248,10 @@ int matchingInputThread(int matchingId) // TODO: The MatchingInput thread is usi // Ignore Incoming Trash Data } + else if (recvresult == 0 && rxbuflen > 0) { + WARN_LOG(SCENET, "InputLoop[%d]: Unknown Port[%s:%u] (Recved=%i, Length=%i)", matchingId, mac2str(&sendermac).c_str(), senderport, recvresult, rxbuflen); + host->NotifyUserMessage(std::string(n->T("Data from incorrect Port")) + std::string(" [") + mac2str(&sendermac) + std::string("]:") + std::to_string(senderport) + std::string(" -> ") + std::to_string(context->port), 1.0, 0x0080ff); + } // Handle Peer Timeouts handleTimeout(context); From 85822f2eeb27058e317b8bec09b6942571d2a8e2 Mon Sep 17 00:00:00 2001 From: ANR2ME Date: Sun, 14 Feb 2021 16:18:47 +0700 Subject: [PATCH 3/6] Making sure src_addr and addrlen args of recvfrom is being set correctly upon use. --- Core/HLE/sceNetAdhoc.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Core/HLE/sceNetAdhoc.cpp b/Core/HLE/sceNetAdhoc.cpp index 8dca3921bd..e0d003769d 100644 --- a/Core/HLE/sceNetAdhoc.cpp +++ b/Core/HLE/sceNetAdhoc.cpp @@ -401,8 +401,8 @@ int DoBlockingPdpRecv(int uid, AdhocSocketRequest& req, s64& result) { } sockaddr_in sin; - memset(&sin, 0, sizeof(sin)); socklen_t sinlen = sizeof(sin); + memset(&sin, 0, sinlen); // On Windows: MSG_TRUNC are not supported on recvfrom (socket error WSAEOPNOTSUPP), so we use dummy buffer as an alternative int ret = recvfrom(uid, dummyPeekBuf64k, dummyPeekBuf64kSize, MSG_PEEK | MSG_NOSIGNAL, (sockaddr*)&sin, &sinlen); @@ -412,6 +412,8 @@ int DoBlockingPdpRecv(int uid, AdhocSocketRequest& req, s64& result) { // Note: UDP must not be received partially, otherwise leftover data in socket's buffer will be discarded if (ret >= 0 && ret <= *req.length) { + sinlen = sizeof(sin); + memset(&sin, 0, sinlen); ret = recvfrom(uid, (char*)req.buffer, *req.length, MSG_NOSIGNAL, (sockaddr*)&sin, &sinlen); // UDP can also receives 0 data, while on TCP receiving 0 data = connection gracefully closed, but not sure whether PDP can send/recv 0 data or not tho *req.length = 0; @@ -1662,6 +1664,7 @@ static int sceNetAdhocPdpRecv(int id, void *addr, void * port, void *buf, void * // Set Address Length (so we get the sender ip) socklen_t sinlen = sizeof(sin); + memset(&sin, 0, sinlen); //sin.sin_len = (uint8_t)sinlen; // Acquire Network Lock @@ -1703,6 +1706,8 @@ static int sceNetAdhocPdpRecv(int id, void *addr, void * port, void *buf, void * return hleLogSuccessVerboseI(SCENET, ERROR_NET_ADHOC_NOT_ENOUGH_SPACE, "not enough space"); //received; } + sinlen = sizeof(sin); + memset(&sin, 0, sinlen); received = recvfrom(pdpsocket.id, (char*)buf, *len, MSG_NOSIGNAL, (sockaddr*)&sin, &sinlen); error = errno; From d323f4fe4db9aeb4c4f5f8dbad27722644a71c1a Mon Sep 17 00:00:00 2001 From: ANR2ME Date: Sun, 21 Feb 2021 00:28:44 +0700 Subject: [PATCH 4/6] Minor AdhocMatching changes. --- Core/HLE/sceNetAdhoc.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/HLE/sceNetAdhoc.cpp b/Core/HLE/sceNetAdhoc.cpp index e0d003769d..67f37a9c85 100644 --- a/Core/HLE/sceNetAdhoc.cpp +++ b/Core/HLE/sceNetAdhoc.cpp @@ -5547,6 +5547,7 @@ void __NetTriggerCallbacks() void __NetMatchingCallbacks() //(int matchingId) { std::lock_guard adhocGuard(adhocEvtMtx); + hleSkipDeadbeef(); int delayus = adhocDefaultDelay; auto params = matchingEvents.begin(); @@ -5558,7 +5559,7 @@ void __NetMatchingCallbacks() //(int matchingId) if (actionAfterMatchingMipsCall < 0) { actionAfterMatchingMipsCall = __KernelRegisterActionType(AfterMatchingMipsCall::Create); } - + DEBUG_LOG(SCENET, "AdhocMatching - Remaining Events: %d", matchingEvents.size()); DEBUG_LOG(SCENET, "AdhocMatchingCallback: [ID=%i][EVENT=%i][%s]", args[0], args[1], mac2str((SceNetEtherAddr*)Memory::GetPointer(args[2])).c_str()); AfterMatchingMipsCall* after = (AfterMatchingMipsCall*)__KernelCreateAction(actionAfterMatchingMipsCall); after->SetData(args[0], args[1], args[2]); @@ -5569,7 +5570,6 @@ void __NetMatchingCallbacks() //(int matchingId) // Must be delayed long enough whenever there is a pending callback. Should it be 10-100ms for Matching Events? or Not Less than the delays on sceNetAdhocMatching HLE? sceKernelDelayThread(delayus); - hleSkipDeadbeef(); } const HLEFunction sceNetAdhoc[] = { From cb61b34b531d7681adf4d9fd7d77578fddeef538 Mon Sep 17 00:00:00 2001 From: ANR2ME Date: Sun, 14 Feb 2021 16:20:27 +0700 Subject: [PATCH 5/6] Minor changes. --- Core/HLE/proAdhoc.cpp | 8 +++--- Core/HLE/sceNetAdhoc.cpp | 62 ++++++++++++++++++++-------------------- 2 files changed, 35 insertions(+), 35 deletions(-) diff --git a/Core/HLE/proAdhoc.cpp b/Core/HLE/proAdhoc.cpp index cada3c4b11..49ae45f457 100644 --- a/Core/HLE/proAdhoc.cpp +++ b/Core/HLE/proAdhoc.cpp @@ -1817,11 +1817,11 @@ int getLocalIp(sockaddr_in* SocketAddress) { serv.sin_addr.s_addr = inet_addr(kGoogleDnsIp); serv.sin_port = htons(kDnsPort); - int err = connect(sock, (const sockaddr*)&serv, sizeof(serv)); + int err = connect(sock, (struct sockaddr*)&serv, sizeof(serv)); if (err != SOCKET_ERROR) { - sockaddr_in name; + struct sockaddr_in name; socklen_t namelen = sizeof(name); - err = getsockname(sock, (sockaddr*)&name, &namelen); + err = getsockname(sock, (struct sockaddr*)&name, &namelen); if (err != SOCKET_ERROR) { SocketAddress->sin_addr = name.sin_addr; // May be we should cache this so it doesn't need to use connect all the time, or even better cache it when connecting to adhoc server to get an accurate IP closesocket(sock); @@ -2126,7 +2126,7 @@ int initNetwork(SceNetAdhocctlAdhocId *adhoc_id){ g_localhostIP.in.sin_port = 0; // Bind Local Address to Socket - iResult = bind(metasocket, &g_localhostIP.addr, sizeof(sockaddr)); + iResult = bind(metasocket, &g_localhostIP.addr, sizeof(g_localhostIP.addr)); if (iResult == SOCKET_ERROR) { ERROR_LOG(SCENET, "Bind to alternate localhost[%s] failed(%i).", inet_ntoa(g_localhostIP.in.sin_addr), iResult); host->NotifyUserMessage(std::string(n->T("Failed to Bind Localhost IP")) + " " + inet_ntoa(g_localhostIP.in.sin_addr), 2.0, 0x0000ff); diff --git a/Core/HLE/sceNetAdhoc.cpp b/Core/HLE/sceNetAdhoc.cpp index 67f37a9c85..d7c51f9234 100644 --- a/Core/HLE/sceNetAdhoc.cpp +++ b/Core/HLE/sceNetAdhoc.cpp @@ -400,12 +400,12 @@ int DoBlockingPdpRecv(int uid, AdhocSocketRequest& req, s64& result) { return 0; } - sockaddr_in sin; + struct sockaddr_in sin; socklen_t sinlen = sizeof(sin); memset(&sin, 0, sinlen); // On Windows: MSG_TRUNC are not supported on recvfrom (socket error WSAEOPNOTSUPP), so we use dummy buffer as an alternative - int ret = recvfrom(uid, dummyPeekBuf64k, dummyPeekBuf64kSize, MSG_PEEK | MSG_NOSIGNAL, (sockaddr*)&sin, &sinlen); + int ret = recvfrom(uid, dummyPeekBuf64k, dummyPeekBuf64kSize, MSG_PEEK | MSG_NOSIGNAL, (struct sockaddr*)&sin, &sinlen); int sockerr = errno; if (ret > 0 && *req.length > 0) memcpy(req.buffer, dummyPeekBuf64k, std::min(ret, *req.length)); @@ -414,7 +414,7 @@ int DoBlockingPdpRecv(int uid, AdhocSocketRequest& req, s64& result) { if (ret >= 0 && ret <= *req.length) { sinlen = sizeof(sin); memset(&sin, 0, sinlen); - ret = recvfrom(uid, (char*)req.buffer, *req.length, MSG_NOSIGNAL, (sockaddr*)&sin, &sinlen); + ret = recvfrom(uid, (char*)req.buffer, *req.length, MSG_NOSIGNAL, (struct sockaddr*)&sin, &sinlen); // UDP can also receives 0 data, while on TCP receiving 0 data = connection gracefully closed, but not sure whether PDP can send/recv 0 data or not tho *req.length = 0; if (ret >= 0) { @@ -503,12 +503,12 @@ int DoBlockingPdpSend(int uid, AdhocSocketRequest& req, s64& result, AdhocSendTa bool retry = false; for (auto peer = targetPeers.peers.begin(); peer != targetPeers.peers.end(); ) { // Fill in Target Structure - sockaddr_in target; + struct sockaddr_in target; target.sin_family = AF_INET; target.sin_addr.s_addr = peer->ip; target.sin_port = htons(peer->port + ((isOriPort && !isPrivateIP(peer->ip)) ? 0 : portOffset)); - int ret = sendto(pdpsocket.id, (const char*)req.buffer, targetPeers.length, MSG_NOSIGNAL, (sockaddr*)&target, sizeof(target)); + int ret = sendto(pdpsocket.id, (const char*)req.buffer, targetPeers.length, MSG_NOSIGNAL, (struct sockaddr*)&target, sizeof(target)); int sockerr = errno; if (ret >= 0) { @@ -649,7 +649,7 @@ int DoBlockingPtpAccept(int uid, AdhocSocketRequest& req, s64& result) { return 0; } - sockaddr_in sin; + struct sockaddr_in sin; memset(&sin, 0, sizeof(sin)); socklen_t sinlen = sizeof(sin); int ret, sockerr; @@ -658,7 +658,7 @@ int DoBlockingPtpAccept(int uid, AdhocSocketRequest& req, s64& result) { ret = IsSocketReady(uid, true, false, &sockerr); if (ret > 0) { // Accept Connection - ret = accept(uid, (sockaddr*)&sin, &sinlen); + ret = accept(uid, (struct sockaddr*)&sin, &sinlen); sockerr = errno; } @@ -701,10 +701,10 @@ int DoBlockingPtpConnect(int uid, AdhocSocketRequest& req, s64& result) { // Connection is ready if (ret > 0) { - sockaddr_in sin; + struct sockaddr_in sin; memset(&sin, 0, sizeof(sin)); socklen_t sinlen = sizeof(sin); - getpeername(uid, (sockaddr*)&sin, &sinlen); + getpeername(uid, (struct sockaddr*)&sin, &sinlen); // Set Connected State ptpsocket.state = ADHOC_PTP_STATE_ESTABLISHED; @@ -1244,7 +1244,7 @@ static int sceNetAdhocPdpCreate(const char *mac, int port, int bufferSize, u32 f setUDPConnReset(usocket, false); // Binding Information for local Port - sockaddr_in addr; + struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; if (isLocalServer) { @@ -1255,12 +1255,12 @@ static int sceNetAdhocPdpCreate(const char *mac, int port, int bufferSize, u32 f // The port might be under 1024 (ie. GTA:VCS use port 1, Ford Street Racing use port 0 (UNUSED_PORT), etc) and already used by other application/host OS, should we add 1024 to the port whenever it tried to use an already used port? // Bound Socket to local Port - int iResult = bind(usocket, (sockaddr *)&addr, sizeof(addr)); + int iResult = bind(usocket, (struct sockaddr*)&addr, sizeof(addr)); if (iResult == 0) { // Update sport with the port assigned internal->lport = ntohs(local.sin_port) socklen_t len = sizeof(addr); - if (getsockname(usocket, (sockaddr*)&addr, &len) == 0) { + if (getsockname(usocket, (struct sockaddr*)&addr, &len) == 0) { if (port + static_cast(portOffset) > 65535 || static_cast(ntohs(addr.sin_port)) - static_cast(portOffset) <= 0) WARN_LOG(SCENET, "sceNetAdhocPdpCreate - Shifting to Negative Port: %d -> %d -> %d", port, port + portOffset, ntohs(addr.sin_port) - portOffset); port = ntohs(addr.sin_port) - portOffset; @@ -1431,7 +1431,7 @@ static int sceNetAdhocPdpSend(int id, const char *mac, u32 port, void *data, int // Single Target if (!isBroadcastMAC(daddr)) { // Fill in Target Structure - sockaddr_in target; + struct sockaddr_in target; target.sin_family = AF_INET; target.sin_port = htons(dport + portOffset); @@ -1444,7 +1444,7 @@ static int sceNetAdhocPdpSend(int id, const char *mac, u32 port, void *data, int //_acquireNetworkLock(); // Send Data. UDP are guaranteed to be sent as a whole or nothing(failed if len > SO_MAX_MSG_SIZE), and never be partially sent/recv - int sent = sendto(pdpsocket.id, (const char *)data, len, MSG_NOSIGNAL, (sockaddr *)&target, sizeof(target)); + int sent = sendto(pdpsocket.id, (const char *)data, len, MSG_NOSIGNAL, (struct sockaddr*)&target, sizeof(target)); int error = errno; if (sent == SOCKET_ERROR) { @@ -1539,12 +1539,12 @@ static int sceNetAdhocPdpSend(int id, const char *mac, u32 port, void *data, int // Iterate Peers for (auto peer : dest.peers) { // Fill in Target Structure - sockaddr_in target; + struct sockaddr_in target; target.sin_family = AF_INET; target.sin_addr.s_addr = peer.ip; target.sin_port = htons(dport + ((isOriPort && !isPrivateIP(peer.ip)) ? 0 : portOffset)); - int sent = sendto(pdpsocket.id, (const char*)data, len, MSG_NOSIGNAL, (sockaddr*)&target, sizeof(target)); + int sent = sendto(pdpsocket.id, (const char*)data, len, MSG_NOSIGNAL, (struct sockaddr*)&target, sizeof(target)); int error = errno; if (sent == SOCKET_ERROR) { DEBUG_LOG(SCENET, "Socket Error (%i) on sceNetAdhocPdpSend[%i:%u->%u](BC) [size=%i]", error, id, getLocalPort(pdpsocket.id), ntohs(target.sin_port), len); @@ -1660,7 +1660,7 @@ static int sceNetAdhocPdpRecv(int id, void *addr, void * port, void *buf, void * } // Sender Address - sockaddr_in sin; + struct sockaddr_in sin; // Set Address Length (so we get the sender ip) socklen_t sinlen = sizeof(sin); @@ -1677,7 +1677,7 @@ static int sceNetAdhocPdpRecv(int id, void *addr, void * port, void *buf, void * // Receive Data. PDP always sent in full size or nothing(failed), recvfrom will always receive in full size as requested (blocking) or failed (non-blocking). If available UDP data is larger than buffer, excess data is lost. // Should peek first for the available data size if it's more than len return ERROR_NET_ADHOC_NOT_ENOUGH_SPACE along with required size in len to prevent losing excess data // On Windows: MSG_TRUNC are not supported on recvfrom (socket error WSAEOPNOTSUPP), so we use dummy buffer as an alternative - received = recvfrom(pdpsocket.id, dummyPeekBuf64k, dummyPeekBuf64kSize, MSG_PEEK | MSG_NOSIGNAL, (sockaddr*)&sin, &sinlen); + received = recvfrom(pdpsocket.id, dummyPeekBuf64k, dummyPeekBuf64kSize, MSG_PEEK | MSG_NOSIGNAL, (struct sockaddr*)&sin, &sinlen); if (received > 0 && *len > 0) memcpy(buf, dummyPeekBuf64k, std::min(received, *len)); @@ -1708,7 +1708,7 @@ static int sceNetAdhocPdpRecv(int id, void *addr, void * port, void *buf, void * } sinlen = sizeof(sin); memset(&sin, 0, sinlen); - received = recvfrom(pdpsocket.id, (char*)buf, *len, MSG_NOSIGNAL, (sockaddr*)&sin, &sinlen); + received = recvfrom(pdpsocket.id, (char*)buf, *len, MSG_NOSIGNAL, (struct sockaddr*)&sin, &sinlen); error = errno; // On Windows: recvfrom on UDP can get error WSAECONNRESET when previous sendto's destination is unreachable (or destination port is not bound), may need to disable SIO_UDP_CONNRESET @@ -3148,7 +3148,7 @@ static int sceNetAdhocPtpOpen(const char *srcmac, int sport, const char *dstmac, setSockNoDelay(tcpsocket, 1); // Binding Information for local Port - sockaddr_in addr; + struct sockaddr_in addr; // addr.sin_len = sizeof(addr); addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; @@ -3158,10 +3158,10 @@ static int sceNetAdhocPtpOpen(const char *srcmac, int sport, const char *dstmac, addr.sin_port = htons(sport + portOffset); // Bound Socket to local Port - if (bind(tcpsocket, (sockaddr*)&addr, sizeof(addr)) == 0) { + if (bind(tcpsocket, (struct sockaddr*)&addr, sizeof(addr)) == 0) { // Update sport with the port assigned internal->lport = ntohs(local.sin_port) socklen_t len = sizeof(addr); - if (getsockname(tcpsocket, (sockaddr*)&addr, &len) == 0) { + if (getsockname(tcpsocket, (struct sockaddr*)&addr, &len) == 0) { if (sport + static_cast(portOffset) > 65535 || static_cast(ntohs(addr.sin_port)) - static_cast(portOffset) <= 0) WARN_LOG(SCENET, "sceNetAdhocPtpOpen - Shifting to Negative Port: %d -> %d -> %d", sport, sport + portOffset, ntohs(addr.sin_port) - portOffset); sport = ntohs(addr.sin_port) - portOffset; @@ -3267,12 +3267,12 @@ int AcceptPtpSocket(int ptpId, int newsocket, sockaddr_in& peeraddr, SceNetEther setSockNoDelay(newsocket, 1); // Local Address Information - sockaddr_in local; + struct sockaddr_in local; memset(&local, 0, sizeof(local)); socklen_t locallen = sizeof(local); // Grab Local Address - if (getsockname(newsocket, (sockaddr*)&local, &locallen) == 0) { + if (getsockname(newsocket, (struct sockaddr*)&local, &locallen) == 0) { // Peer MAC SceNetEtherAddr mac; @@ -3407,7 +3407,7 @@ static int sceNetAdhocPtpAccept(int id, u32 peerMacAddrPtr, u32 peerPortPtr, int if (ptpsocket.state == ADHOC_PTP_STATE_LISTEN) { hleEatMicro(500); // Address Information - sockaddr_in peeraddr; + struct sockaddr_in peeraddr; memset(&peeraddr, 0, sizeof(peeraddr)); socklen_t peeraddrlen = sizeof(peeraddr); int error; @@ -3416,7 +3416,7 @@ static int sceNetAdhocPtpAccept(int id, u32 peerMacAddrPtr, u32 peerPortPtr, int int newsocket = IsSocketReady(ptpsocket.id, true, false, &error); if (newsocket > 0) { // Accept Connection - newsocket = accept(ptpsocket.id, (sockaddr*)&peeraddr, &peeraddrlen); + newsocket = accept(ptpsocket.id, (struct sockaddr*)&peeraddr, &peeraddrlen); error = errno; } @@ -3488,7 +3488,7 @@ int NetAdhocPtp_Connect(int id, int timeout, int flag, bool allowForcedConnect) if (ptpsocket.state == ADHOC_PTP_STATE_CLOSED || ptpsocket.state == ADHOC_PTP_STATE_SYN_SENT) { hleEatMicro(500); // Target Address - sockaddr_in sin; + struct sockaddr_in sin; memset(&sin, 0, sizeof(sin)); // Setup Target Address @@ -3503,7 +3503,7 @@ int NetAdhocPtp_Connect(int id, int timeout, int flag, bool allowForcedConnect) // Connect Socket to Peer // NOTE: Based on what i read at stackoverflow, The First Non-blocking POSIX connect will always returns EAGAIN/EWOULDBLOCK because it returns without waiting for ACK/handshake, But GvG Next Plus is treating non-blocking PtpConnect just like blocking connect, May be on a real PSP the first non-blocking sceNetAdhocPtpConnect can be successfull? - int connectresult = connect(ptpsocket.id, (sockaddr*)&sin, sizeof(sin)); + int connectresult = connect(ptpsocket.id, (struct sockaddr*)&sin, sizeof(sin)); // Grab Error Code int errorcode = errno; @@ -3713,7 +3713,7 @@ static int sceNetAdhocPtpListen(const char *srcmac, int sport, int bufsize, int setSockNoDelay(tcpsocket, 1); // Binding Information for local Port - sockaddr_in addr; + struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; if (isLocalServer) { @@ -3723,10 +3723,10 @@ static int sceNetAdhocPtpListen(const char *srcmac, int sport, int bufsize, int int iResult = 0; // Bound Socket to local Port - if ((iResult = bind(tcpsocket, (sockaddr*)&addr, sizeof(addr))) == 0) { + if ((iResult = bind(tcpsocket, (struct sockaddr*)&addr, sizeof(addr))) == 0) { // Update sport with the port assigned internal->lport = ntohs(local.sin_port) socklen_t len = sizeof(addr); - if (getsockname(tcpsocket, (sockaddr*)&addr, &len) == 0) { + if (getsockname(tcpsocket, (struct sockaddr*)&addr, &len) == 0) { if (sport + static_cast(portOffset) > 65535 || static_cast(ntohs(addr.sin_port)) - static_cast(portOffset) <= 0) WARN_LOG(SCENET, "sceNetAdhocPtpListen - Shifting to Negative Port: %d -> %d -> %d", sport, sport + portOffset, ntohs(addr.sin_port) - portOffset); sport = ntohs(addr.sin_port) - portOffset; From 4ee08ef73b70091670997cf7d3eb632e99bd1069 Mon Sep 17 00:00:00 2001 From: ANR2ME Date: Sun, 14 Feb 2021 16:24:37 +0700 Subject: [PATCH 6/6] Making sure the port is bound to an interface when using bind with INADDR_ANY. Seems to fix #14130 --- Core/HLE/sceNetAdhoc.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Core/HLE/sceNetAdhoc.cpp b/Core/HLE/sceNetAdhoc.cpp index d7c51f9234..1f17b77646 100644 --- a/Core/HLE/sceNetAdhoc.cpp +++ b/Core/HLE/sceNetAdhoc.cpp @@ -1251,13 +1251,17 @@ static int sceNetAdhocPdpCreate(const char *mac, int port, int bufferSize, u32 f getLocalIp(&addr); } - addr.sin_port = htons(port + portOffset); + addr.sin_port = htons(static_cast(port + static_cast(portOffset))); // The port might be under 1024 (ie. GTA:VCS use port 1, Ford Street Racing use port 0 (UNUSED_PORT), etc) and already used by other application/host OS, should we add 1024 to the port whenever it tried to use an already used port? // Bound Socket to local Port int iResult = bind(usocket, (struct sockaddr*)&addr, sizeof(addr)); if (iResult == 0) { + // Workaround: Send a dummy 0 size message to AdhocServer IP to make sure the socket actually bound to an address when binded with INADDR_ANY before using getsockname, seems to fix sending from incorrect port issue on MGS:PW on Android + addr.sin_addr.s_addr = g_adhocServerIP.in.sin_addr.s_addr; + addr.sin_port = 0; + sendto(usocket, dummyPeekBuf64k, 0, MSG_NOSIGNAL, (struct sockaddr*)&addr, sizeof(addr)); // Update sport with the port assigned internal->lport = ntohs(local.sin_port) socklen_t len = sizeof(addr); if (getsockname(usocket, (struct sockaddr*)&addr, &len) == 0) { @@ -3155,7 +3159,7 @@ static int sceNetAdhocPtpOpen(const char *srcmac, int sport, const char *dstmac, if (isLocalServer) { getLocalIp(&addr); } - addr.sin_port = htons(sport + portOffset); + addr.sin_port = htons(static_cast(sport + static_cast(portOffset))); // Bound Socket to local Port if (bind(tcpsocket, (struct sockaddr*)&addr, sizeof(addr)) == 0) { @@ -3719,7 +3723,7 @@ static int sceNetAdhocPtpListen(const char *srcmac, int sport, int bufsize, int if (isLocalServer) { getLocalIp(&addr); } - addr.sin_port = htons(sport + portOffset); + addr.sin_port = htons(static_cast(sport + static_cast(portOffset))); int iResult = 0; // Bound Socket to local Port