mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-13 17:49:29 +01:00
Windows recvfrom doesn't support MSG_TRUNC, so we're using dummy buffer with max size as alternative for peeking actual size of the next pending message.
This commit is contained in:
1 parent
fc452c0dfd
commit
0ce2c2c6e9
4 files changed
+19
-12
No files matched your search
@@ -60,6 +60,8 @@ uint16_t portOffset;
|
||||
uint32_t minSocketTimeoutUS;
|
||||
uint32_t fakePoolSize = 0;
|
||||
SceNetAdhocMatchingContext * contexts = NULL;
|
||||
char* dummyPeekBuf64k = NULL;
|
||||
int dummyPeekBuf64kSize = 65536;
|
||||
int one = 1;
|
||||
bool friendFinderRunning = false;
|
||||
SceNetAdhocctlPeerInfo * friends = NULL;
|
||||
@@ -1908,12 +1910,7 @@ u_long getAvailToRecv(int sock, int udpBufferSize) {
|
||||
return 0;
|
||||
|
||||
if (udpBufferSize > 0 && n > 0) {
|
||||
// TODO: Cap number of bytes of full DGRAM message(s) up to buffer size
|
||||
char buf[8];
|
||||
// Each recv can only received one message, not sure how to read the next pending msg without actually receiving the first one
|
||||
err = recvfrom(sock, buf, sizeof(buf), MSG_PEEK | MSG_NOSIGNAL | MSG_TRUNC, NULL, NULL);
|
||||
if (err >= 0)
|
||||
return (u_long)err;
|
||||
// TODO: Cap number of bytes of full DGRAM message(s) up to buffer size, but may cause Warriors Orochi 2 to get FPS drops
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
@@ -917,6 +917,8 @@ extern int defaultWlanChannel; // Default WLAN Channel for Auto, JPCSP uses 11
|
||||
|
||||
extern uint32_t fakePoolSize;
|
||||
extern SceNetAdhocMatchingContext * contexts;
|
||||
extern char* dummyPeekBuf64k;
|
||||
extern int dummyPeekBuf64kSize;
|
||||
extern int one;
|
||||
extern bool friendFinderRunning;
|
||||
extern SceNetAdhocctlPeerInfo * friends;
|
||||
|
||||
@@ -203,6 +203,7 @@ void __NetInit() {
|
||||
g_adhocServerIP.in.sin_port = htons(SERVER_PORT); //27312 // Maybe read this from config too
|
||||
g_adhocServerIP.in.sin_addr.s_addr = INADDR_NONE;
|
||||
|
||||
dummyPeekBuf64k = (char*)malloc(dummyPeekBuf64kSize);
|
||||
InitLocalhostIP();
|
||||
|
||||
SceNetEtherAddr mac;
|
||||
@@ -235,6 +236,8 @@ void __NetShutdown() {
|
||||
|
||||
// Since PortManager supposed to be general purpose for whatever port forwarding PPSSPP needed, may be we shouldn't clear & restore ports in here? it will be cleared and restored by PortManager's destructor when exiting PPSSPP anyway
|
||||
__UPnPShutdown();
|
||||
|
||||
free(dummyPeekBuf64k);
|
||||
}
|
||||
|
||||
static void __UpdateApctlHandlers(u32 oldState, u32 newState, u32 flag, u32 error) {
|
||||
|
||||
@@ -412,9 +412,11 @@ int DoBlockingPdpRecv(int uid, AdhocSocketRequest& req, s64& result) {
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
socklen_t sinlen = sizeof(sin);
|
||||
|
||||
// On Windows: Using MSG_TRUNC can sometimes getting socket error WSAEOPNOTSUPP, may be the socket wasn't ready to received anything right after created & binded?
|
||||
int ret = recvfrom(uid, (char*)req.buffer, *req.length, MSG_PEEK | MSG_NOSIGNAL | MSG_TRUNC, (sockaddr*)&sin, &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 sockerr = errno;
|
||||
if (ret > 0 && *req.length > 0)
|
||||
memcpy(req.buffer, dummyPeekBuf64k, std::min(ret, *req.length));
|
||||
|
||||
// Note: UDP must not be received partially, otherwise leftover data in socket's buffer will be discarded
|
||||
if (ret >= 0 && ret <= *req.length) {
|
||||
@@ -453,7 +455,7 @@ int DoBlockingPdpRecv(int uid, AdhocSocketRequest& req, s64& result) {
|
||||
result = 0;
|
||||
}
|
||||
// On Windows: recvfrom on UDP can get error WSAECONNRESET when previous sendto's destination is unreachable (or destination port is not bound yet), may need to disable SIO_UDP_CONNRESET error
|
||||
else if (sockerr == EAGAIN || sockerr == EWOULDBLOCK || sockerr == ECONNRESET || sockerr == EOPNOTSUPP) {
|
||||
else if (sockerr == EAGAIN || sockerr == EWOULDBLOCK || sockerr == ECONNRESET) {
|
||||
u64 now = (u64)(time_now_d() * 1000000.0);
|
||||
if (req.timeout == 0 || now - req.startTime <= req.timeout) {
|
||||
// Try again later
|
||||
@@ -1691,8 +1693,11 @@ 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: Using MSG_TRUNC can sometimes getting socket error WSAEOPNOTSUPP, may be the socket wasn't ready to received anything right after created & binded?
|
||||
received = recvfrom(pdpsocket.id, (char*)buf, *len, MSG_PEEK | MSG_NOSIGNAL | MSG_TRUNC, (sockaddr*)&sin, &sinlen);
|
||||
// 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);
|
||||
if (received > 0 && *len > 0)
|
||||
memcpy(buf, dummyPeekBuf64k, std::min(received, *len));
|
||||
|
||||
if (received != SOCKET_ERROR && *len < received) {
|
||||
WARN_LOG(SCENET, "sceNetAdhocPdpRecv[%i:%u]: Peeked %u/%u bytes from %s:%u\n", id, getLocalPort(pdpsocket.id), received, *len, inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
|
||||
*len = received;
|
||||
@@ -1722,7 +1727,7 @@ static int sceNetAdhocPdpRecv(int id, void *addr, void * port, void *buf, void *
|
||||
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
|
||||
if (received == SOCKET_ERROR && (error == EAGAIN || error == EWOULDBLOCK || error == ECONNRESET || error == EOPNOTSUPP)) {
|
||||
if (received == SOCKET_ERROR && (error == EAGAIN || error == EWOULDBLOCK || error == ECONNRESET)) {
|
||||
if (flag == 0) {
|
||||
// Simulate blocking behaviour with non-blocking socket
|
||||
u64 threadSocketId = ((u64)__KernelGetCurThread()) << 32 | pdpsocket.id;
|
||||
|
||||
Reference in new issue
Block a user