Merge pull request #14060 from ANR2ME/adhoc

[Adhoc] Fix possible lock issue and Updated PdpStat
This commit is contained in:
Henrik Rydgård authored and GitHub committed 2021-02-04 10:47:24 +01:00
commit d3d5ff0d0d
3 files changed
+34 -9

No files matched your search

+25 -3
View File
@@ -1896,13 +1896,35 @@ uint16_t getLocalPort(int sock) {
return ntohs(localAddr.sin_port);
}
u_long getAvailToRecv(int sock) {
u_long getAvailToRecv(int sock, int udpBufferSize) {
u_long n = 0; // Typical MTU size is 1500
int err = -1;
#if defined(_WIN32) // May not be available on all platform
ioctlsocket(sock, FIONREAD, &n);
err = ioctlsocket(sock, FIONREAD, &n);
#else
ioctl(sock, FIONREAD, &n);
err = ioctl(sock, FIONREAD, &n);
#endif
if (err < 0)
return 0;
if (udpBufferSize > 0 && n > 0) {
// Cap number of bytes of full DGRAM message(s?) up to buffer size
static int lastUdpBufSize = 0;
static char* buf = NULL;
if (udpBufferSize > lastUdpBufSize) {
// Reusing temp buffer to prevent causing too many fragmentation due to repeated alloc -> free (was getting out of memory issue)
char *tmp = (char*)realloc(buf, udpBufferSize);
if (tmp) {
buf = tmp;
lastUdpBufSize = udpBufferSize;
}
}
// Does each recv can only received one message?
err = recvfrom(sock, buf, udpBufferSize, MSG_PEEK | MSG_NOSIGNAL | MSG_TRUNC, NULL, NULL);
//free(buf); // Repeated alloc -> free seems to cause too many fragmentation and ended getting out of memory due to too many alloc -> free
if (err >= 0)
return (u_long)err;
}
return n;
}
+3 -1
View File
@@ -1271,8 +1271,10 @@ bool isPrivateIP(uint32_t ip);
/*
* Get Number of bytes available in buffer to be Received
* @param sock fd
* @param udpBufferSize (UDP only)
*/
u_long getAvailToRecv(int sock);
u_long getAvailToRecv(int sock, int udpBufferSize = 0);
/*
* Get UDP Socket Max Message Size
+6 -5
View File
@@ -2943,10 +2943,9 @@ static int sceNetAdhocGetPdpStat(u32 structSize, u32 structAddr) {
auto sock = adhocSockets[j];
if (sock != NULL && sock->type == SOCK_PDP) {
// Set available bytes to be received. With FIONREAD There might be ghosting 1 byte in recv buffer when remote peer's socket got closed (ie. Warriors Orochi 2) Attempting to recv this ghost 1 byte will result to socket error 10054 (may need to disable SIO_UDP_CONNRESET error)
sock->data.pdp.rcv_sb_cc = getAvailToRecv(sock->data.pdp.id);
// TODO: It seems real PSP respecting the socket buffer size arg, so we may need to cap the value to the buffer size arg since we use larger buffer, but may cause Warriors Orochi 2 to get slower performance.
// Note: Capping available data on UDP/PDP can causes data loss if the game tried to read the whole capped buffer size while containing partial/truncated message.
//sock->data.pdp.rcv_sb_cc = std::min(sock->data.pdp.rcv_sb_cc, (u32_le)sock->buffer_size);
// It seems real PSP respecting the socket buffer size arg, so we may need to cap the value up to the buffer size arg since we use larger buffer, for PDP/UDP the total size must not contains partial/truncated message to avoid data loss.
// TODO: We may need to manage PDP messages ourself by reading each msg 1-by-1 and moving it to our internal buffer(msg array) in order to calculate the correct messages size that can fit into buffer size when there are more than 1 messages in the recv buffer (simulate FIONREAD)
sock->data.pdp.rcv_sb_cc = getAvailToRecv(sock->data.pdp.id, sock->buffer_size);
// Copy Socket Data from Internal Memory
memcpy(&buf[i], &sock->data.pdp, sizeof(SceNetAdhocPdpStat));
@@ -4661,8 +4660,10 @@ int NetAdhocMatching_Start(int matchingId, int evthPri, int evthPartitionId, int
// Create PDP Socket
int sock = sceNetAdhocPdpCreate((const char*)&item->mac, static_cast<int>(item->port), item->rxbuflen, 0);
item->socket = sock;
if (sock < 1)
if (sock < 1) {
peerlock.unlock();
return hleLogError(SCENET, ERROR_NET_ADHOC_MATCHING_PORT_IN_USE, "adhoc matching port in use");
}
// Create & Start the Fake PSP Thread ("matching_ev%d" and "matching_io%d")
netAdhocValidateLoopMemory();