Merge pull request #18350 from anr2me/adhoc_matching

[AdhocMatching] Detects leaving players better
This commit is contained in:
Henrik Rydgård 2024-09-18 11:16:30 +02:00 committed by GitHub
commit e3eba11b43
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 41 additions and 22 deletions

View file

@ -1062,10 +1062,12 @@ void handleTimeout(SceNetAdhocMatchingContext * context)
// Timeout! Apparently the latest GetGlobalTimeUsScaled (ie. now) have a possibility to be smaller than previous GetGlobalTimeUsScaled (ie. lastping) thus resulting a negative number when subtracted :(
if (peer->state != 0 && static_cast<s64>(now - peer->lastping) > static_cast<s64>(context->timeout))
{
// Spawn Timeout Event
// Spawn Timeout Event. FIXME: Should we allow TIMEOUT Event to intervene joining process of Parent-Child too just like P2P Mode? (ie. Crazy Taxi uses P2P Mode)
if ((context->mode == PSP_ADHOC_MATCHING_MODE_CHILD && peer->state == PSP_ADHOC_MATCHING_PEER_PARENT) ||
(context->mode == PSP_ADHOC_MATCHING_MODE_PARENT && peer->state == PSP_ADHOC_MATCHING_PEER_CHILD) ||
(context->mode == PSP_ADHOC_MATCHING_MODE_P2P && peer->state == PSP_ADHOC_MATCHING_PEER_P2P)) {
(context->mode == PSP_ADHOC_MATCHING_MODE_P2P &&
(peer->state == PSP_ADHOC_MATCHING_PEER_P2P || peer->state == PSP_ADHOC_MATCHING_PEER_OFFER || peer->state == PSP_ADHOC_MATCHING_PEER_INCOMING_REQUEST || peer->state == PSP_ADHOC_MATCHING_PEER_OUTGOING_REQUEST || peer->state == PSP_ADHOC_MATCHING_PEER_CANCEL_IN_PROGRESS)))
{
// FIXME: TIMEOUT event should only be triggered on Parent/P2P mode and for Parent/P2P peer?
spawnLocalEvent(context, PSP_ADHOC_MATCHING_EVENT_TIMEOUT, &peer->mac, 0, NULL);

View file

@ -4940,7 +4940,7 @@ static int sceNetAdhocMatchingCreate(int mode, int maxnum, int port, int rxbufle
if (keepalive_int < 1) context->keepalive_int = PSP_ADHOCCTL_PING_TIMEOUT; else context->keepalive_int = keepalive_int; // client might set this to 0
context->keepalivecounter = init_count; // used to multiply keepalive_int as timeout
context->timeout = (((u64)(keepalive_int)+(u64)rexmt_int) * (u64)init_count);
context->timeout += adhocDefaultTimeout; // For internet play we need higher timeout than what the game wanted
context->timeout += 500000; // For internet play we need higher timeout than what the game wanted
context->handler = handler;
context->peerPort = new std::map<SceNetEtherAddr, u16_le>();
@ -5927,7 +5927,7 @@ void __NetMatchingCallbacks() //(int matchingId)
DEBUG_LOG(Log::sceNet, "AdhocMatching - Remaining Events: %zu", matchingEvents.size());
auto peer = findPeer(context, (SceNetEtherAddr*)Memory::GetPointer(args[2]));
// Discard HELLO Events when in the middle of joining, as some games (ie. Super Pocket Tennis) might tried to join again (TODO: Need to confirm whether sceNetAdhocMatchingSelectTarget supposed to be blocking the current thread or not)
if (peer == NULL || (args[1] != PSP_ADHOC_MATCHING_EVENT_HELLO || (peer->state != PSP_ADHOC_MATCHING_PEER_OUTGOING_REQUEST && peer->state != PSP_ADHOC_MATCHING_PEER_INCOMING_REQUEST))) {
if (peer == NULL || (args[1] != PSP_ADHOC_MATCHING_EVENT_HELLO || (peer->state != PSP_ADHOC_MATCHING_PEER_OUTGOING_REQUEST && peer->state != PSP_ADHOC_MATCHING_PEER_INCOMING_REQUEST && peer->state != PSP_ADHOC_MATCHING_PEER_CANCEL_IN_PROGRESS))) {
DEBUG_LOG(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);
@ -5942,7 +5942,7 @@ 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);
sceKernelDelayThreadCB(delayus);
}
const HLEFunction sceNetAdhoc[] = {
@ -6727,7 +6727,10 @@ void sendCancelPacket(SceNetAdhocMatchingContext * context, SceNetEtherAddr * ma
}
// Delete Peer
else deletePeer(context, peer);
else {
// Instead of removing peer immediately, We should give a little time before removing the peer and let it timed out? so it can send the BYE packet when stopping AdhocMatching after Canceling it
peer->lastping = CoreTiming::GetGlobalTimeUsScaled();
}
}
}
@ -6903,7 +6906,7 @@ void sendByePacket(SceNetAdhocMatchingContext * context)
for (; peer != NULL; peer = peer->next)
{
// Peer of Interest
if (peer->state == PSP_ADHOC_MATCHING_PEER_PARENT || peer->state == PSP_ADHOC_MATCHING_PEER_CHILD || peer->state == PSP_ADHOC_MATCHING_PEER_P2P)
if (peer->state == PSP_ADHOC_MATCHING_PEER_PARENT || peer->state == PSP_ADHOC_MATCHING_PEER_CHILD || peer->state == PSP_ADHOC_MATCHING_PEER_P2P || peer->state == PSP_ADHOC_MATCHING_PEER_CANCEL_IN_PROGRESS)
{
// Bye Opcode
uint8_t opcode = PSP_ADHOC_MATCHING_PACKET_BYE;
@ -7232,7 +7235,8 @@ void actOnCancelPacket(SceNetAdhocMatchingContext * context, SceNetEtherAddr * s
spawnLocalEvent(context, PSP_ADHOC_MATCHING_EVENT_DENY, sendermac, optlen, opt);
// Delete Peer from List
deletePeer(context, peer);
//deletePeer(context, peer);
peer->lastping = 0;
}
// Kicked from Room
@ -7265,7 +7269,8 @@ void actOnCancelPacket(SceNetAdhocMatchingContext * context, SceNetEtherAddr * s
spawnLocalEvent(context, PSP_ADHOC_MATCHING_EVENT_CANCEL, sendermac, optlen, opt);
// Delete Peer from List
deletePeer(context, peer);
//deletePeer(context, peer);
peer->lastping = 0;
}
// Leave Room
@ -7275,7 +7280,8 @@ void actOnCancelPacket(SceNetAdhocMatchingContext * context, SceNetEtherAddr * s
spawnLocalEvent(context, PSP_ADHOC_MATCHING_EVENT_LEAVE, sendermac, optlen, opt);
// Delete Peer from List
deletePeer(context, peer);
//deletePeer(context, peer);
peer->lastping = 0;
}
}
@ -7291,8 +7297,9 @@ void actOnCancelPacket(SceNetAdhocMatchingContext * context, SceNetEtherAddr * s
// Spawn Deny Event
spawnLocalEvent(context, PSP_ADHOC_MATCHING_EVENT_DENY, sendermac, optlen, opt);
// Delete Peer from List
deletePeer(context, peer);
// FIXME: Delete Peer from List?
// Instead of removing the peer immediately, we should let it timedout, otherwise inviter in Crazy Taxi will wait forever without getting timedout, since handleTimeout need the peer data to exist.
peer->lastping = 0;
}
// Kicked from Room
@ -7302,7 +7309,8 @@ void actOnCancelPacket(SceNetAdhocMatchingContext * context, SceNetEtherAddr * s
spawnLocalEvent(context, PSP_ADHOC_MATCHING_EVENT_LEAVE, sendermac, optlen, opt);
// Delete Peer from List
deletePeer(context, peer);
//deletePeer(context, peer);
peer->lastping = 0;
}
// Cancel Join Request
@ -7312,7 +7320,8 @@ void actOnCancelPacket(SceNetAdhocMatchingContext * context, SceNetEtherAddr * s
spawnLocalEvent(context, PSP_ADHOC_MATCHING_EVENT_CANCEL, sendermac, optlen, opt);
// Delete Peer from List
deletePeer(context, peer);
//deletePeer(context, peer);
peer->lastping = 0;
}
}
}
@ -7460,10 +7469,11 @@ void actOnByePacket(SceNetAdhocMatchingContext * context, SceNetEtherAddr * send
// We know this guy
if (peer != NULL)
{
// P2P or Child Bye
// P2P or Child Bye. FIXME: Should we allow BYE Event to intervene joining process of Parent-Child too just like P2P Mode? (ie. Crazy Taxi uses P2P Mode)
if ((context->mode == PSP_ADHOC_MATCHING_MODE_PARENT && peer->state == PSP_ADHOC_MATCHING_PEER_CHILD) ||
(context->mode == PSP_ADHOC_MATCHING_MODE_CHILD && peer->state == PSP_ADHOC_MATCHING_PEER_CHILD) ||
(context->mode == PSP_ADHOC_MATCHING_MODE_P2P && peer->state == PSP_ADHOC_MATCHING_PEER_P2P))
(context->mode == PSP_ADHOC_MATCHING_MODE_P2P &&
(peer->state == PSP_ADHOC_MATCHING_PEER_P2P || peer->state == PSP_ADHOC_MATCHING_PEER_OFFER || peer->state == PSP_ADHOC_MATCHING_PEER_INCOMING_REQUEST || peer->state == PSP_ADHOC_MATCHING_PEER_OUTGOING_REQUEST || peer->state == PSP_ADHOC_MATCHING_PEER_CANCEL_IN_PROGRESS)))
{
if (context->mode != PSP_ADHOC_MATCHING_MODE_CHILD) {
// Spawn Leave / Kick Event. FIXME: DISCONNECT event should only be triggered on Parent/P2P mode and for Parent/P2P peer?
@ -7524,7 +7534,7 @@ int matchingEventThread(int matchingId)
peerlock.unlock();
// Messages on Stack ready for processing
if (context != NULL && context->event_stack != NULL)
while (context != NULL && context->event_stack != NULL)
{
// Claim Stack
context->eventlock->lock();
@ -7666,7 +7676,7 @@ int matchingInputThread(int matchingId) // TODO: The MatchingInput thread is usi
// Multithreading Unlock
peerlock.unlock();
if (context != NULL) {
while (context != NULL && context->inputRunning && !Core_IsStepping()) {
now = CoreTiming::GetGlobalTimeUsScaled(); //time_now_d()*1000000.0;
// Hello Message Sending Context with unoccupied Slots
@ -7685,15 +7695,23 @@ int matchingInputThread(int matchingId) // TODO: The MatchingInput thread is usi
}
// Ping Required
if (context->keepalive_int > 0)
if (context->keepalive_int > 0) {
if (static_cast<s64>(now - lastping) >= static_cast<s64>(context->keepalive_int))
{
// Handle Peer Timeouts
handleTimeout(context);
// Broadcast Ping Message
broadcastPingMessage(context);
// Update Ping Timer
lastping = now;
}
}
else {
// FIXME: Should we checks for Timeout too when the game doesn't set the keep alive interval?
handleTimeout(context);
}
// Messages on Stack ready for processing
if (context->input_stack != NULL)
@ -7825,9 +7843,8 @@ int matchingInputThread(int matchingId) // TODO: The MatchingInput thread is usi
// Ignore Incoming Trash Data
}
// Handle Peer Timeouts
handleTimeout(context);
else
break;
}
// Share CPU Time
sleep_ms(10); //1 //sceKernelDelayThread(10000);