Skip to content

Commit

Permalink
prudp: Dont expect sessionId to match for PING+ACK
Browse files Browse the repository at this point in the history
Fixes friend service connection periodically timing-out on Pretendo.

Seems that unlike Nintendo's servers, Pretendo doesn't set sessionId for PING ack packets.
  • Loading branch information
Exzap committed Apr 13, 2024
1 parent d5a8530 commit 9c28a72
Showing 1 changed file with 12 additions and 6 deletions.
18 changes: 12 additions & 6 deletions src/Cemu/nex/prudp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -452,9 +452,7 @@ prudpIncomingPacket::prudpIncomingPacket(prudpStreamSettings_t* streamSettings,
}
else
{
#ifdef CEMU_DEBUG_ASSERT
assert_dbg();
#endif
cemu_assert_suspicious();
}
}

Expand Down Expand Up @@ -696,6 +694,8 @@ void prudpClient::handleIncomingPacket(prudpIncomingPacket* incomingPacket)
if (currentConnectionState == STATE_CONNECTING)
{
lastPingTimestamp = prudpGetMSTimestamp();
if(serverSessionId != 0)
cemuLog_logDebug(LogType::Force, "PRUDP: ServerSessionId is already set");
serverSessionId = incomingPacket->sessionId;
currentConnectionState = STATE_CONNECTED;
//printf("Connection established. ClientSession %02x ServerSession %02x\n", clientSessionId, serverSessionId);
Expand Down Expand Up @@ -763,7 +763,6 @@ bool prudpClient::update()
sint32 r = recvfrom(socketUdp, (char*)receiveBuffer, sizeof(receiveBuffer), 0, &receiveFrom, &receiveFromLen);
if (r >= 0)
{
//printf("RECV 0x%04x byte\n", r);
// todo: Verify sender (receiveFrom)
// calculate packet size
sint32 pIdx = 0;
Expand All @@ -772,18 +771,25 @@ bool prudpClient::update()
sint32 packetLength = prudpPacket::calculateSizeFromPacketData(receiveBuffer + pIdx, r - pIdx);
if (packetLength <= 0 || (pIdx + packetLength) > r)
{
//printf("Invalid packet length\n");
cemuLog_logDebug(LogType::Force, "PRUDP: Invalid packet length");
break;
}
prudpIncomingPacket* incomingPacket = new prudpIncomingPacket(&streamSettings, receiveBuffer + pIdx, packetLength);

pIdx += packetLength;
if (incomingPacket->hasError())
{
cemuLog_logDebug(LogType::Force, "PRUDP: Packet error");
delete incomingPacket;
break;
}
if (incomingPacket->type != prudpPacket::TYPE_CON && incomingPacket->sessionId != serverSessionId)
// sessionId validation is complicated and depends on specific flags and type combinations. It does not seem to cover all packet types
bool validateSessionId = serverSessionId != 0;
if((incomingPacket->type == prudpPacket::TYPE_PING && (incomingPacket->flags&prudpPacket::FLAG_ACK) != 0))
validateSessionId = false; // PING + ack -> disable session id validation. Pretendo's friend server sends PING ack packets without setting the sessionId (it is 0)
if (validateSessionId && incomingPacket->sessionId != serverSessionId)
{
cemuLog_logDebug(LogType::Force, "PRUDP: Invalid session id");
delete incomingPacket;
continue; // different session
}
Expand Down

0 comments on commit 9c28a72

Please sign in to comment.