Merge pull request #14870 from ANR2ME/adhoc_matching

[AdhocMatching] An attempt to handle unknown/incorrect source port better on AdhocMatching
This commit is contained in:
AdamN authored and GitHub committed 2021-09-18 10:14:20 +07:00
commit 9aa8fa8553
2 files changed
+86 -28

No files matched your search

+19 -3
View File
@@ -221,6 +221,19 @@ typedef struct SceNetEtherAddr {
uint8_t data[ETHER_ADDR_LEN];
} PACK SceNetEtherAddr;
inline bool operator<(const SceNetEtherAddr& lhs, const SceNetEtherAddr& rhs) {
uint64_t l = 0;
uint64_t r = 0;
const uint8_t* lp = lhs.data;
const uint8_t* rp = rhs.data;
for (int8_t i = 5; i >= 0; i--) {
int8_t sb = (CHAR_BIT * i);
l |= (uint64_t)*lp++ << sb;
r |= (uint64_t)*rp++ << sb;
}
return (l < r);
}
// Broadcast MAC
extern uint8_t broadcastMAC[ETHER_ADDR_LEN];
@@ -486,12 +499,15 @@ typedef struct SceNetAdhocMatchingContext {
// Maximum Number of Peers (for HOST, P2P)
s32_le maxpeers;
// Local MAC Address
SceNetEtherAddr mac;
// Peer List for Connectees
SceNetAdhocMatchingMemberInternal *peerlist; // SceNetAdhocMatchingMemberInfo[Emu]
// Peer Port list
std::map<SceNetEtherAddr, u16_le> *peerPort;
// Local MAC Address
SceNetEtherAddr mac;
// Local PDP Port
u16_le port;
+67 -25
View File
@@ -4488,6 +4488,8 @@ int NetAdhocMatching_Delete(int matchingId) {
free(item->hello);
free(item->rxbuf);
clearPeerList(item); //deleteAllMembers(item);
(*item->peerPort).clear();
delete item->peerPort;
// Destroy locks
item->eventlock->lock(); // Make sure it's not locked when being deleted
item->eventlock->unlock();
@@ -4638,6 +4640,7 @@ static int sceNetAdhocMatchingCreate(int mode, int maxnum, int port, int rxbufle
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->handler = handler;
context->peerPort = new std::map<SceNetEtherAddr, u16_le>();
// Fill in Selfpeer
context->mac = localmac;
@@ -5468,16 +5471,16 @@ int sceNetAdhocMatchingAbortSendData(int matchingId, const char *mac) {
// Get the maximum memory usage by the matching library
static int sceNetAdhocMatchingGetPoolMaxAlloc() {
ERROR_LOG(SCENET, "UNIMPL sceNetAdhocMatchingGetPoolMaxAlloc()");
ERROR_LOG(SCENET, "UNIMPL sceNetAdhocMatchingGetPoolMaxAlloc() at %08x", currentMIPS->pc);
if (!g_Config.bEnableWlan)
return -1;
// Lazy way out - hardcoded return value
return fakePoolSize/2; // (50 * 1024);
return hleLogDebug(SCENET, fakePoolSize/2, "faked value");
}
int sceNetAdhocMatchingGetPoolStat(u32 poolstatPtr) {
DEBUG_LOG(SCENET, "UNTESTED sceNetAdhocMatchingGetPoolStat(%08x)", poolstatPtr);
DEBUG_LOG(SCENET, "UNTESTED sceNetAdhocMatchingGetPoolStat(%08x) at %08x", poolstatPtr, currentMIPS->pc);
if (!g_Config.bEnableWlan)
return -1;
@@ -5500,11 +5503,11 @@ int sceNetAdhocMatchingGetPoolStat(u32 poolstatPtr) {
}
// Invalid Argument
return ERROR_NET_ADHOC_MATCHING_INVALID_ARG;
return hleLogError(SCENET, ERROR_NET_ADHOC_MATCHING_INVALID_ARG, "adhocmatching invalid arg");
}
// Uninitialized Library
return ERROR_NET_ADHOC_MATCHING_NOT_INITIALIZED;
return hleLogError(SCENET, ERROR_NET_ADHOC_MATCHING_NOT_INITIALIZED, "adhocmatching not initialized");
}
void __NetTriggerCallbacks()
@@ -6010,9 +6013,24 @@ void broadcastPingMessage(SceNetAdhocMatchingContext * context)
uint8_t ping = PSP_ADHOC_MATCHING_PACKET_PING;
// Send Broadcast
context->socketlock->lock();
sceNetAdhocPdpSend(context->socket, (const char*)(SceNetEtherAddr *)broadcastMAC, context->port, &ping, sizeof(ping), 0, ADHOC_F_NONBLOCK);
context->socketlock->unlock();
// FIXME: Not sure whether this PING supposed to be sent only to AdhocMatching members or to everyone in Adhocctl Group, since we already pinging the AdhocServer to avoid getting kicked out of Adhocctl Group
peerlock.lock();
auto peer = friends; // Use context->peerlist if only need to send to AdhocMatching members
for (; peer != NULL; peer = peer->next) {
// Skipping soon to be removed peer
if (peer->last_recv == 0)
continue;
u16_le port = context->port;
auto it = (*context->peerPort).find(peer->mac_addr);
if (it != (*context->peerPort).end())
port = it->second;
context->socketlock->lock();
sceNetAdhocPdpSend(context->socket, (const char*)&peer->mac_addr, port, &ping, sizeof(ping), 0, ADHOC_F_NONBLOCK);
context->socketlock->unlock();
}
peerlock.unlock();
}
/**
@@ -6053,10 +6071,24 @@ void broadcastHelloMessage(SceNetAdhocMatchingContext * context)
DataToHexString(10, 0, context->hello, context->hellolen, &hellohex);
DEBUG_LOG(SCENET, "HELLO Dump (%d bytes):\n%s", context->hellolen, hellohex.c_str());
// Send Broadcast
context->socketlock->lock();
sceNetAdhocPdpSend(context->socket, (const char*)(SceNetEtherAddr *)broadcastMAC, context->port, hello, 5 + context->hellolen, 0, ADHOC_F_NONBLOCK);
context->socketlock->unlock();
// Send Broadcast, so everyone know we have a room here
peerlock.lock();
SceNetAdhocctlPeerInfo* peer = friends;
for (; peer != NULL; peer = peer->next) {
// Skipping soon to be removed peer
if (peer->last_recv == 0)
continue;
u16_le port = context->port;
auto it = (*context->peerPort).find(peer->mac_addr);
if (it != (*context->peerPort).end())
port = it->second;
context->socketlock->lock();
sceNetAdhocPdpSend(context->socket, (const char*)&peer->mac_addr, port, hello, 5 + context->hellolen, 0, ADHOC_F_NONBLOCK);
context->socketlock->unlock();
}
peerlock.unlock();
// Free Memory, not needed since it may be reused again later
//free(hello);
@@ -6132,7 +6164,7 @@ void sendAcceptPacket(SceNetAdhocMatchingContext * context, SceNetEtherAddr * ma
// Send Data
context->socketlock->lock();
sceNetAdhocPdpSend(context->socket, (const char*)mac, context->port, accept, 9 + optlen + siblingbuflen, 0, ADHOC_F_NONBLOCK);
sceNetAdhocPdpSend(context->socket, (const char*)mac, (*context->peerPort)[*mac], accept, 9 + optlen + siblingbuflen, 0, ADHOC_F_NONBLOCK);
context->socketlock->unlock();
// Free Memory
@@ -6176,7 +6208,7 @@ void sendJoinPacket(SceNetAdhocMatchingContext * context, SceNetEtherAddr * mac,
// Send Data
context->socketlock->lock();
sceNetAdhocPdpSend(context->socket, (const char*)mac, context->port, join, 5 + optlen, 0, ADHOC_F_NONBLOCK);
sceNetAdhocPdpSend(context->socket, (const char*)mac, (*context->peerPort)[*mac], join, 5 + optlen, 0, ADHOC_F_NONBLOCK);
context->socketlock->unlock();
// Free Memory
@@ -6211,7 +6243,7 @@ void sendCancelPacket(SceNetAdhocMatchingContext * context, SceNetEtherAddr * ma
// Send Data
context->socketlock->lock();
sceNetAdhocPdpSend(context->socket, (const char*)mac, context->port, cancel, 5 + optlen, 0, ADHOC_F_NONBLOCK);
sceNetAdhocPdpSend(context->socket, (const char*)mac, (*context->peerPort)[*mac], cancel, 5 + optlen, 0, ADHOC_F_NONBLOCK);
context->socketlock->unlock();
// Free Memory
@@ -6273,7 +6305,7 @@ void sendBulkDataPacket(SceNetAdhocMatchingContext * context, SceNetEtherAddr *
// Send Data
context->socketlock->lock();
sceNetAdhocPdpSend(context->socket, (const char*)mac, context->port, send, 5 + datalen, 0, ADHOC_F_NONBLOCK);
sceNetAdhocPdpSend(context->socket, (const char*)mac, (*context->peerPort)[*mac], send, 5 + datalen, 0, ADHOC_F_NONBLOCK);
context->socketlock->unlock();
// Free Memory
@@ -6322,7 +6354,7 @@ void sendBirthPacket(SceNetAdhocMatchingContext * context, SceNetEtherAddr * mac
{
// Send Packet
context->socketlock->lock();
int sent = sceNetAdhocPdpSend(context->socket, (const char*)&peer->mac, context->port, packet, sizeof(packet), 0, ADHOC_F_NONBLOCK);
int sent = sceNetAdhocPdpSend(context->socket, (const char*)&peer->mac, (*context->peerPort)[peer->mac], packet, sizeof(packet), 0, ADHOC_F_NONBLOCK);
context->socketlock->unlock();
// Log Send Success
@@ -6365,7 +6397,7 @@ void sendDeathPacket(SceNetAdhocMatchingContext * context, SceNetEtherAddr * mac
// Send Bye Packet
context->socketlock->lock();
sceNetAdhocPdpSend(context->socket, (const char*)&peer->mac, context->port, packet, sizeof(packet[0]), 0, ADHOC_F_NONBLOCK);
sceNetAdhocPdpSend(context->socket, (const char*)&peer->mac, (*context->peerPort)[peer->mac], packet, sizeof(packet[0]), 0, ADHOC_F_NONBLOCK);
context->socketlock->unlock();
}
else
@@ -6377,7 +6409,7 @@ void sendDeathPacket(SceNetAdhocMatchingContext * context, SceNetEtherAddr * mac
// Send Death Packet
context->socketlock->lock();
sceNetAdhocPdpSend(context->socket, (const char*)&peer->mac, context->port, packet, sizeof(packet), 0, ADHOC_F_NONBLOCK);
sceNetAdhocPdpSend(context->socket, (const char*)&peer->mac, (*context->peerPort)[peer->mac], packet, sizeof(packet), 0, ADHOC_F_NONBLOCK);
context->socketlock->unlock();
}
}
@@ -6405,7 +6437,7 @@ void sendByePacket(SceNetAdhocMatchingContext * context)
// Send Bye Packet
context->socketlock->lock();
sceNetAdhocPdpSend(context->socket, (const char*)&peer->mac, context->port, &opcode, sizeof(opcode), 0, ADHOC_F_NONBLOCK);
sceNetAdhocPdpSend(context->socket, (const char*)&peer->mac, (*context->peerPort)[peer->mac], &opcode, sizeof(opcode), 0, ADHOC_F_NONBLOCK);
context->socketlock->unlock();
}
}
@@ -7250,7 +7282,8 @@ int matchingInputThread(int matchingId) // TODO: The MatchingInput thread is usi
context->socketlock->unlock();
// Received Data from a Sender that interests us
if (recvresult == 0 && rxbuflen > 0 && context->port == senderport)
// Note: There are cases where the sender port might be re-mapped by router or ISP, so we shouldn't check the source port.
if (recvresult == 0 && rxbuflen > 0)
{
// Log Receive Success
if (context->rxbuf[0] > 1) {
@@ -7269,6 +7302,19 @@ int matchingInputThread(int matchingId) // TODO: The MatchingInput thread is usi
else {
WARN_LOG(SCENET, "InputLoop[%d]: Unknown Peer[%s:%u] (Recved=%i, Length=%i)", matchingId, mac2str(&sendermac).c_str(), senderport, recvresult, rxbuflen);
}
// Show a warning if other player is having their port being re-mapped, thus that other player may have issue with the communication.
// Note: That other player may need to switch side between host and join, or reboot their router to solve this issue.
if (context->port != senderport && senderport != (*context->peerPort)[sendermac]) {
char name[9] = {};
if (peer != NULL)
truncate_cpy(name, sizeof(name), (const char*)peer->nickname.data);
WARN_LOG(SCENET, "InputLoop[%d]: Unknown Source Port from [%s][%s:%u -> %u] (Recved=%i, Length=%i)", matchingId, name, mac2str(&sendermac).c_str(), senderport, context->port, recvresult, rxbuflen);
host->NotifyUserMessage(std::string(n->T("AM: Data from Unknown Port")) + std::string(" [") + std::string(name) + std::string("]:") + std::to_string(senderport) + std::string(" -> ") + std::to_string(context->port) + std::string(" (") + std::to_string(portOffset) + std::string(")"), 2.0, 0x0080ff);
}
// Keep tracks of re-mapped peer's ports for further communication.
// Note: This will only works if this player were able to receives data on normal port from other players (ie. this player's port wasn't remapped)
(*context->peerPort)[sendermac] = senderport;
peerlock.unlock();
// Ping Packet
@@ -7303,10 +7349,6 @@ 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) + std::string(" (") + std::to_string(portOffset) + std::string(")"), 1.0, 0x0080ff);
}
// Handle Peer Timeouts
handleTimeout(context);