Improved multiplayer compatibility on some games (ie. GTA VCS, Naruto Ultimate Ninja Heroes 3, DBZ Shin Budokai 2, Power Stone Collection, .hack//Link, etc)

This commit is contained in:
ANR2ME 2019-12-24 00:04:03 +07:00 committed by Henrik Rydgård
parent af2ed00232
commit fb7d50e5c2
8 changed files with 1428 additions and 657 deletions

View file

@ -27,6 +27,7 @@
#include <cstring>
#include "util/text/parsers.h"
#include "thread/threadutil.h"
#include "Core/Core.h"
#include "Core/Host.h"
#include "Core/HLE/sceKernelInterrupt.h"
@ -46,7 +47,7 @@ SceNetAdhocctlScanInfo * networks = NULL;
SceNetAdhocctlScanInfo * newnetworks = NULL;
int threadStatus = ADHOCCTL_STATE_DISCONNECTED;
bool IsAdhocctlInCB = false;
int actionAfterAdhocMipsCall;
int actionAfterMatchingMipsCall;
// Broadcast MAC
@ -59,7 +60,6 @@ std::thread friendFinderThread;
std::recursive_mutex peerlock;
SceNetAdhocPdpStat * pdp[255];
SceNetAdhocPtpStat * ptp[255];
uint32_t localip;
std::vector<std::string> chatLog;
std::string name = "";
std::string incoming = "";
@ -67,11 +67,10 @@ std::string message = "";
bool chatScreenVisible = false;
bool updateChatScreen = false;
int newChat = 0;
bool isLocalServer = false;
sockaddr localIP; // This might serves the same purpose with existing "localip" above, but since this is copied from my old code so here it is (too lazy to rewrite the code)
int isLocalMAC(const SceNetEtherAddr * addr) {
bool isLocalMAC(const SceNetEtherAddr * addr) {
SceNetEtherAddr saddr;
getLocalMac(&saddr);
@ -82,32 +81,59 @@ int isLocalMAC(const SceNetEtherAddr * addr) {
return (match == 0);
}
int isPDPPortInUse(uint16_t port) {
bool isPDPPortInUse(uint16_t port) {
// Iterate Elements
int i = 0; for (; i < 255; i++) if (pdp[i] != NULL && pdp[i]->lport == port) return 1;
for (int i = 0; i < 255; i++) if (pdp[i] != NULL && pdp[i]->lport == port) return true;
// Unused Port
return 0;
return false;
}
int isPTPPortInUse(uint16_t port) {
bool isPTPPortInUse(uint16_t port) {
// Iterate Sockets
int i = 0; for(; i < 255; i++) if(ptp[i] != NULL && ptp[i]->lport == port) return 1;
for(int i = 0; i < 255; i++) if(ptp[i] != NULL && ptp[i]->lport == port) return true;
// Unused Port
return 0;
return false;
}
char* mac2str(SceNetEtherAddr* mac) {
if (mac == NULL) return ":::::";
#if defined(_WIN32)
static __declspec(thread) char str[18];
#else
static __thread char str[18];
#endif
snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x", mac->data[0], mac->data[1], mac->data[2], mac->data[3], mac->data[4], mac->data[5]);
return str;
}
char* mac2str(SceNetEtherAddr* mac, char* str, size_t size) {
if (mac == NULL || str == NULL || size < 18) return NULL;
snprintf(str, size, "%02x:%02x:%02x:%02x:%02x:%02x", mac->data[0], mac->data[1], mac->data[2], mac->data[3], mac->data[4], mac->data[5]);
return str;
}
SceNetAdhocMatchingMemberInternal* addMember(SceNetAdhocMatchingContext * context, SceNetEtherAddr * mac) {
if (context == NULL || mac == NULL) return NULL;
SceNetAdhocMatchingMemberInternal * peer = findPeer(context, mac);
// Already existed
if (peer != NULL) {
char tmpmac[18];
WARN_LOG(SCENET, "Member Peer Already Existed! Updating [%s]", mac2str(mac, tmpmac));
peer->lastping = CoreTiming::GetGlobalTimeUsScaled();
}
// Member is not added yet
if (peer == NULL) {
else {
peer = (SceNetAdhocMatchingMemberInternal *)malloc(sizeof(SceNetAdhocMatchingMemberInternal));
if (peer != NULL) {
memset(peer, 0, sizeof(SceNetAdhocMatchingMemberInternal));
peer->mac = *mac;
peer->lastping = CoreTiming::GetGlobalTimeUsScaled();
peer->next = context->peerlist;
context->peerlist = peer;
}
@ -124,14 +150,15 @@ void addFriend(SceNetAdhocctlConnectPacketS2C * packet) {
SceNetAdhocctlPeerInfo * peer = findFriend(&packet->mac);
// Already existed
if (peer != NULL) {
char tmpmac[18];
WARN_LOG(SCENET, "Friend Peer Already Existed! Updating [%s][%s][%s]", packet->name.data, mac2str(&packet->mac, tmpmac), inet_ntoa(*(in_addr*)&packet->ip));
peer->nickname = packet->name;
peer->mac_addr = packet->mac;
peer->ip_addr = packet->ip;
// Update TimeStamp
peer->last_recv = CoreTiming::GetGlobalTimeUsScaled();
}
else
{
else {
// Allocate Structure
peer = (SceNetAdhocctlPeerInfo *)malloc(sizeof(SceNetAdhocctlPeerInfo));
// Allocated Structure
@ -198,7 +225,7 @@ void changeBlockingMode(int fd, int nonblocking) {
#endif
}
int countAvailableNetworks(void) {
int countAvailableNetworks() {
// Network Count
int count = 0;
@ -236,11 +263,12 @@ void freeGroupsRecursive(SceNetAdhocctlScanInfo * node) {
// Free Memory
free(node);
node = NULL;
}
void deleteAllPDP(void) {
void deleteAllPDP() {
// Iterate Element
int i = 0; for (; i < 255; i++) {
for (int i = 0; i < 255; i++) {
// Active Socket
if (pdp[i] != NULL) {
// Close Socket
@ -255,9 +283,9 @@ void deleteAllPDP(void) {
}
}
void deleteAllPTP(void) {
void deleteAllPTP() {
// Iterate Element
int i = 0; for (; i < 255; i++) {
for (int i = 0; i < 255; i++) {
// Active Socket
if (ptp[i] != NULL) {
// Close Socket
@ -283,36 +311,39 @@ void deleteFriendByIP(uint32_t ip) {
for (; peer != NULL; peer = peer->next) {
// Found Peer
if (peer->ip_addr == ip) {
// Instead of removing it from the list we'll make it timeout since most Matching games are moving group and may still need the peer data
peer->last_recv = 0;
// Multithreading Lock
peerlock.lock();
// Unlink Left (Beginning)
if(prev == NULL)friends = peer->next;
/*if (prev == NULL) friends = peer->next;
// Unlink Left (Other)
else prev->next = peer->next;
*/
char tmpmac[18];
INFO_LOG(SCENET, "Removing Friend Peer %s [%s]", mac2str(&peer->mac_addr, tmpmac), inet_ntoa(*(in_addr*)&peer->ip_addr));
// Free Memory
//free(peer);
//peer = NULL;
// Instead of removing it from the list we'll make it timed out since most Matching games are moving group and may still need the peer data thus not recognizing it as Unknown peer
peer->last_recv = 0; //CoreTiming::GetGlobalTimeUsScaled();
// Multithreading Unlock
peerlock.unlock();
// Free Memory
free(peer);
peer = NULL;
// Stop Search
break;
}
// Set Previous Reference
// TODO: Should this be used by something?
prev = peer;
}
}
int findFreeMatchingID(void) {
int findFreeMatchingID() {
// Minimum Matching ID
int min = 1;
@ -320,13 +351,15 @@ int findFreeMatchingID(void) {
int max = 0;
// Find highest Matching ID
SceNetAdhocMatchingContext * item = contexts; for (; item != NULL; item = item->next) {
SceNetAdhocMatchingContext * item = contexts;
for (; item != NULL; item = item->next) {
// New Maximum
if (max < item->id) max = item->id;
}
// Find unoccupied ID
int i = min; for (; i < max; i++) {
int i = min;
for (; i < max; i++) {
// Found unoccupied ID
if (findMatchingContext(i) == NULL) return i;
}
@ -337,7 +370,8 @@ int findFreeMatchingID(void) {
SceNetAdhocMatchingContext * findMatchingContext(int id) {
// Iterate Matching Context List
SceNetAdhocMatchingContext * item = contexts; for (; item != NULL; item = item->next) { // Found Matching ID
SceNetAdhocMatchingContext * item = contexts;
for (; item != NULL; item = item->next) { // Found Matching ID
if (item->id == id) return item;
}
@ -353,7 +387,8 @@ SceNetAdhocMatchingContext * findMatchingContext(int id) {
SceNetAdhocMatchingMemberInternal * findOutgoingRequest(SceNetAdhocMatchingContext * context)
{
// Iterate Peer List for Matching Target
SceNetAdhocMatchingMemberInternal * peer = context->peerlist; for (; peer != NULL; peer = peer->next)
SceNetAdhocMatchingMemberInternal * peer = context->peerlist;
for (; peer != NULL; peer = peer->next)
{
// Found Peer in List
if (peer->state == PSP_ADHOC_MATCHING_PEER_OUTGOING_REQUEST) return peer;
@ -369,6 +404,8 @@ SceNetAdhocMatchingMemberInternal * findOutgoingRequest(SceNetAdhocMatchingConte
*/
void postAcceptCleanPeerList(SceNetAdhocMatchingContext * context)
{
int delcount = 0;
int peercount = 0;
// Acquire Peer Lock
peerlock.lock();
@ -380,14 +417,20 @@ void postAcceptCleanPeerList(SceNetAdhocMatchingContext * context)
SceNetAdhocMatchingMemberInternal * next = peer->next;
// Unneeded Peer
if (peer->state != PSP_ADHOC_MATCHING_PEER_CHILD && peer->state != PSP_ADHOC_MATCHING_PEER_P2P && peer->state != PSP_ADHOC_MATCHING_PEER_PARENT) deletePeer(context, peer);
if (peer->state != PSP_ADHOC_MATCHING_PEER_CHILD && peer->state != PSP_ADHOC_MATCHING_PEER_P2P && peer->state != PSP_ADHOC_MATCHING_PEER_PARENT) {
deletePeer(context, peer);
delcount++;
}
// Move to Next Peer
peer = next;
peercount++;
}
// Free Peer Lock
peerlock.unlock();
INFO_LOG(SCENET, "Removing Unneeded Peer (%i/%i)", delcount, peercount);
}
/**
@ -404,7 +447,7 @@ void postAcceptAddSiblings(SceNetAdhocMatchingContext * context, int siblingcoun
uint8_t * siblings_u8 = (uint8_t *)siblings;
// Iterate Siblings
int i = 0; for (; i < siblingcount; i++)
for (int i = 0; i < siblingcount; i++)
{
// Allocate Memory
SceNetAdhocMatchingMemberInternal * sibling = (SceNetAdhocMatchingMemberInternal *)malloc(sizeof(SceNetAdhocMatchingMemberInternal));
@ -431,7 +474,8 @@ void postAcceptAddSiblings(SceNetAdhocMatchingContext * context, int siblingcoun
// Spawn Established Event
spawnLocalEvent(context, PSP_ADHOC_MATCHING_EVENT_ESTABLISHED, &sibling->mac, 0, NULL);
INFO_LOG(SCENET, "Accepting Peer %02X:%02X:%02X:%02X:%02X:%02X", sibling->mac.data[0], sibling->mac.data[1], sibling->mac.data[2], sibling->mac.data[3], sibling->mac.data[4], sibling->mac.data[5]);
char tmpmac[18];
INFO_LOG(SCENET, "Accepting Peer %s", mac2str(&sibling->mac, tmpmac));
}
}
}
@ -441,14 +485,17 @@ void postAcceptAddSiblings(SceNetAdhocMatchingContext * context, int siblingcoun
* @param context Matching Context Pointer
* @return Number of Children
*/
s32_le countChildren(SceNetAdhocMatchingContext * context)
s32_le countChildren(SceNetAdhocMatchingContext * context, const bool excludeTimedout)
{
// Children Counter
s32_le count = 0;
// Iterate Peer List for Matching Target
SceNetAdhocMatchingMemberInternal * peer = context->peerlist; for (; peer != NULL; peer = peer->next)
SceNetAdhocMatchingMemberInternal * peer = context->peerlist;
for (; peer != NULL; peer = peer->next)
{
// Exclude timedout members?
if (!excludeTimedout || peer->lastping != 0)
// Increase Children Counter
if (peer->state == PSP_ADHOC_MATCHING_PEER_CHILD) count++;
}
@ -466,7 +513,8 @@ s32_le countChildren(SceNetAdhocMatchingContext * context)
SceNetAdhocMatchingMemberInternal * findPeer(SceNetAdhocMatchingContext * context, SceNetEtherAddr * mac)
{
// Iterate Peer List for Matching Target
SceNetAdhocMatchingMemberInternal * peer = context->peerlist; for (; peer != NULL; peer = peer->next)
SceNetAdhocMatchingMemberInternal * peer = context->peerlist;
for (; peer != NULL; peer = peer->next)
{
// Found Peer in List
if (memcmp(&peer->mac, mac, sizeof(SceNetEtherAddr)) == 0)
@ -488,7 +536,8 @@ SceNetAdhocMatchingMemberInternal * findPeer(SceNetAdhocMatchingContext * contex
SceNetAdhocMatchingMemberInternal * findParent(SceNetAdhocMatchingContext * context)
{
// Iterate Peer List for Matching Target
SceNetAdhocMatchingMemberInternal * peer = context->peerlist; for (; peer != NULL; peer = peer->next)
SceNetAdhocMatchingMemberInternal * peer = context->peerlist;
for (; peer != NULL; peer = peer->next)
{
// Found Peer in List
if (peer->state == PSP_ADHOC_MATCHING_PEER_PARENT) return peer;
@ -503,12 +552,14 @@ SceNetAdhocMatchingMemberInternal * findParent(SceNetAdhocMatchingContext * cont
* @param context Matching Context Pointer
* @return Internal Peer Reference or... NULL
*/
SceNetAdhocMatchingMemberInternal * findP2P(SceNetAdhocMatchingContext * context)
SceNetAdhocMatchingMemberInternal * findP2P(SceNetAdhocMatchingContext * context, const bool excludeTimedout)
{
// Iterate Peer List for Matching Target
SceNetAdhocMatchingMemberInternal * peer = context->peerlist;
for (; peer != NULL; peer = peer->next)
{
// Exclude timedout members?
if (!excludeTimedout || peer->lastping != 0)
// Found Peer in List
if (peer->state == PSP_ADHOC_MATCHING_PEER_P2P) return peer;
}
@ -550,7 +601,8 @@ void deletePeer(SceNetAdhocMatchingContext * context, SceNetAdhocMatchingMemberI
// Beginning Item
else context->peerlist = item->next;
INFO_LOG(SCENET, "Removing Peer %02X:%02X:%02X:%02X:%02X:%02X", peer->mac.data[0], peer->mac.data[1], peer->mac.data[2], peer->mac.data[3], peer->mac.data[4], peer->mac.data[5]);
char tmpmac[18];
INFO_LOG(SCENET, "Removing Member Peer %s", mac2str(&peer->mac, tmpmac));
}
// Free Peer Memory
@ -741,7 +793,7 @@ void sendDeathMessage(SceNetAdhocMatchingContext * context, SceNetAdhocMatchingM
* @param context Matching Context Pointer
* @return Number of Connected Peers
*/
uint32_t countConnectedPeers(SceNetAdhocMatchingContext * context)
uint32_t countConnectedPeers(SceNetAdhocMatchingContext * context, const bool excludeTimedout)
{
// Peer Count
uint32_t count = 0;
@ -750,7 +802,7 @@ uint32_t countConnectedPeers(SceNetAdhocMatchingContext * context)
if (context->mode == PSP_ADHOC_MATCHING_MODE_PARENT)
{
// Number of Children + 1 Parent (Self)
count = countChildren(context) + 1;
count = countChildren(context, excludeTimedout) + 1;
}
// Child Mode
@ -763,7 +815,7 @@ uint32_t countConnectedPeers(SceNetAdhocMatchingContext * context)
if (findParent(context) != NULL)
{
// Add Number of Siblings + 1 Parents
count += countChildren(context) + 1;
count += countChildren(context, excludeTimedout) + 1;
}
}
@ -774,7 +826,7 @@ uint32_t countConnectedPeers(SceNetAdhocMatchingContext * context)
count = 1;
// Connected to another P2P Client
if (findP2P(context) != NULL)
if (findP2P(context, excludeTimedout) != NULL)
{
// Add P2P Brother
count++;
@ -801,31 +853,35 @@ void spawnLocalEvent(SceNetAdhocMatchingContext * context, int event, SceNetEthe
/**
* Handle Timeouts in Matching Context
* @param context Matchi]ng Context Pointer
* @param context Matching Context Pointer
*/
void handleTimeout(SceNetAdhocMatchingContext * context)
{
peerlock.lock();
// Iterate Peer List
SceNetAdhocMatchingMemberInternal * peer = context->peerlist; while (peer != NULL)
SceNetAdhocMatchingMemberInternal * peer = context->peerlist;
while (peer != NULL && contexts != NULL && coreState != CORE_POWERDOWN)
{
// Get Next Pointer (to avoid crash on memory freeing)
SceNetAdhocMatchingMemberInternal * next = peer->next;
u64_le now = CoreTiming::GetGlobalTimeUsScaled(); //real_time_now()*1000000.0
// Timeout!
// Timeout!, may be we shouldn't kick timedout members ourself and let the game do it
if ((now - peer->lastping) >= context->timeout)
{
// Spawn Timeout Event
if ((context->mode == PSP_ADHOC_MATCHING_MODE_CHILD && (peer->state == PSP_ADHOC_MATCHING_PEER_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))
spawnLocalEvent(context, PSP_ADHOC_MATCHING_EVENT_TIMEOUT, &peer->mac, 0, NULL);
(context->mode == PSP_ADHOC_MATCHING_MODE_P2P && peer->state == PSP_ADHOC_MATCHING_PEER_P2P)) {
spawnLocalEvent(context, PSP_ADHOC_MATCHING_EVENT_TIMEOUT, &peer->mac, 0, NULL); // This is the only code that use PSP_ADHOC_MATCHING_EVENT_TIMEOUT, should we let it timedout?
}
INFO_LOG(SCENET, "TimedOut Peer %02X:%02X:%02X:%02X:%02X:%02X (%lldms)", peer->mac.data[0], peer->mac.data[1], peer->mac.data[2], peer->mac.data[3], peer->mac.data[4], peer->mac.data[5], (context->timeout/1000));
char tmpmac[18];
INFO_LOG(SCENET, "TimedOut Member Peer %s (%lldms)", mac2str(&peer->mac, tmpmac), (context->timeout/1000));
// Delete Peer from List
deletePeer(context, peer);
//peer->lastping = 0; //Let's just make the game kick timedout members during sceNetAdhocMatchingGetMembers
}
// Move Pointer
@ -845,6 +901,7 @@ void clearStackRecursive(ThreadMessage * node)
// Free Last Existing Node of List (NULL is handled in _free)
free(node);
node = NULL;
}
/**
@ -901,6 +958,8 @@ void clearPeerList(SceNetAdhocMatchingContext * context)
// Delete Peer
free(peer); //deletePeer(context, peer);
// Instead of removing peer immediately, We should give a little time before removing the peer and let it timed out? just in case the game is in the middle of communicating with the peer on another thread so it won't recognize it as Unknown peer
//peer->lastping = CoreTiming::GetGlobalTimeUsScaled();
// Move Pointer
peer = context->peerlist; //peer = next;
@ -910,36 +969,23 @@ void clearPeerList(SceNetAdhocMatchingContext * context)
peerlock.unlock();
}
bool IsMatchingInCallback(SceNetAdhocMatchingContext * context) {
bool inCB = false;
if (context == NULL) return inCB;
context->eventlock->lock(); //peerlock.lock();
inCB = (/*context != NULL &&*/ context->IsMatchingInCB);
context->eventlock->unlock(); //peerlock.unlock();
return inCB;
}
// It seems After Actions being called in reverse order of Mipscall order (ie. MipsCall order of ACCEPT(6)->ESTABLISH(7) getting AfterAction order of ESTABLISH(7)->ACCEPT(6)
void AfterMatchingMipsCall::run(MipsCall &call) {
if (!context || !context->eventlock)
return;
DEBUG_LOG(SCENET, "Entering AfterMatchingMipsCall::run [ID=%i][Event=%d] [cbId: %u]", context->id, EventID, call.cbId);
//u32 v0 = currentMIPS->r[MIPS_REG_V0];
if (__IsInInterrupt()) ERROR_LOG(SCENET, "AfterMatchingMipsCall::run [ID=%i][Event=%d] is Returning Inside an Interrupt!", context->id, EventID);
//while (__IsInInterrupt()) sleep_ms(1); // Must not sleep inside callback handler
context->eventlock->lock(); //peerlock.lock();
//SceNetAdhocMatchingContext * context = findMatchingContext(ID);
//if (context != NULL)
{
context->IsMatchingInCB = false;
if (context == NULL) {
peerlock.lock();
context = findMatchingContext(contextID);
peerlock.unlock();
}
context->eventlock->unlock(); //peerlock.unlock();
//call.setReturnValue(v0);
u32 v0 = currentMIPS->r[MIPS_REG_V0];
if (__IsInInterrupt()) ERROR_LOG(SCENET, "AfterMatchingMipsCall::run [ID=%i][Event=%d] is Returning Inside an Interrupt!", contextID, EventID);
if (Memory::IsValidAddress(bufAddr)) userMemory.Free(bufAddr);
DEBUG_LOG(SCENET, "Leaving AfterMatchingMipsCall::run [ID=%i][Event=%d] [retV0: %08x]", context->id, EventID, currentMIPS->r[MIPS_REG_V0]);
SetMatchingInCallback(context, false);
DEBUG_LOG(SCENET, "AfterMatchingMipsCall::run [ID=%i][Event=%d] [cbId: %u][retV0: %08x]", contextID, EventID, call.cbId, v0);
//call.setReturnValue(v0);
}
void AfterMatchingMipsCall::SetContextID(u32 ContextID, u32 eventId, u32_le BufAddr) {
void AfterMatchingMipsCall::SetData(int ContextID, int eventId, u32_le BufAddr) {
contextID = ContextID;
EventID = eventId;
bufAddr = BufAddr;
peerlock.lock();
@ -947,61 +993,100 @@ void AfterMatchingMipsCall::SetContextID(u32 ContextID, u32 eventId, u32_le BufA
peerlock.unlock();
}
bool SetMatchingInCallback(SceNetAdhocMatchingContext* context, bool IsInCB) {
if (context == NULL) return false;
context->eventlock->lock(); //peerlock.lock();
context->IsMatchingInCB = IsInCB;
context->eventlock->unlock(); //peerlock.unlock();
return IsInCB;
}
bool IsMatchingInCallback(SceNetAdhocMatchingContext* context) {
bool inCB = false;
if (context == NULL) return inCB;
context->eventlock->lock(); //peerlock.lock();
inCB = (context->IsMatchingInCB);
context->eventlock->unlock(); //peerlock.unlock();
return inCB;
}
void AfterAdhocMipsCall::run(MipsCall& call) {
u32 v0 = currentMIPS->r[MIPS_REG_V0];
if (__IsInInterrupt()) ERROR_LOG(SCENET, "AfterAdhocMipsCall::run [ID=%i][Event=%d] is Returning Inside an Interrupt!", HandlerID, EventID);
SetAdhocctlInCallback(false);
DEBUG_LOG(SCENET, "AfterAdhocMipsCall::run [ID=%i][Event=%d] [cbId: %u][retV0: %08x]", HandlerID, EventID, call.cbId, v0);
//call.setReturnValue(v0);
}
void AfterAdhocMipsCall::SetData(int handlerID, int eventId, u32_le ArgsAddr) {
HandlerID = handlerID;
EventID = eventId;
argsAddr = ArgsAddr;
}
int SetAdhocctlInCallback(bool IsInCB) {
std::lock_guard<std::recursive_mutex> adhocGuard(adhocEvtMtx);
IsAdhocctlInCB += (IsInCB?1:-1);
return IsAdhocctlInCB;
}
int IsAdhocctlInCallback() {
std::lock_guard<std::recursive_mutex> adhocGuard(adhocEvtMtx);
int inCB = IsAdhocctlInCB;
return inCB;
}
// Make sure MIPS calls have been fully executed before the next notifyAdhocctlHandlers
void notifyAdhocctlHandlers(u32 flag, u32 error) {
__UpdateAdhocctlHandlers(flag, error);
// TODO: We should use after action instead of guessing the time like this
//sleep_ms(20); // Ugly workaround to give time for the mips callback to fully executed, usually only need <16ms
}
// Matching callback is void function: typedef void(*SceNetAdhocMatchingHandler)(int id, int event, SceNetEtherAddr * peer, int optlen, void * opt);
// Important! The MIPS call need to be fully executed before the next MIPS call invoked, as the game (ie. DBZ Tag Team) may need to prepare something for the next callback event to use
// Note: Must not lock peerlock within this function to prevent race-condition with other thread whos owning peerlock and trying to lock context->eventlock owned by this thread
void notifyMatchingHandler(SceNetAdhocMatchingContext * context, ThreadMessage * msg, void * opt, u32 &bufAddr, u32 &bufLen, u32_le * args) {
//u32_le args[5] = { 0, 0, 0, 0, 0 };
/*if ((s32)bufLen < (msg->optlen + 8)) {
bufLen = msg->optlen + 8;
if (Memory::IsValidAddress(bufAddr)) userMemory.Free(bufAddr);
bufAddr = userMemory.Alloc(bufLen); // Max bufLen should be context->rxbuflen
INFO_LOG(SCENET, "MatchingHandler: Alloc(%i -> %i) = %08x", msg->optlen + 8, bufLen, bufAddr);
}*/
void notifyMatchingHandler(SceNetAdhocMatchingContext * context, ThreadMessage * msg, void * opt, u32_le &bufAddr, u32_le &bufLen, u32_le * args) {
// Don't share buffer address space with other mipscall in the queue since mipscalls aren't immediately executed
MatchingArgs argsNew;
bufAddr = userMemory.Alloc(bufLen); // We will free this after returning from mipscall
u8 * optPtr = Memory::GetPointer(bufAddr);
memcpy(optPtr, &msg->mac, sizeof(msg->mac));
if (msg->optlen > 0) memcpy(optPtr + 8, opt, msg->optlen);
u32_le dataBufLen = msg->optlen + 8; //max(bufLen, msg->optlen + 8);
u32_le dataBufAddr = userMemory.Alloc(dataBufLen); // We will free this memory after returning from mipscall
uint8_t * dataPtr = Memory::GetPointer(dataBufAddr);
memcpy(dataPtr, &msg->mac, sizeof(msg->mac));
if (msg->optlen > 0)
memcpy(dataPtr + 8, opt, msg->optlen);
argsNew.data[0] = context->id;
argsNew.data[1] = msg->opcode;
argsNew.data[2] = bufAddr; // PSP_GetScratchpadMemoryBase() + 0x6000;
argsNew.data[2] = dataBufAddr;
argsNew.data[3] = msg->optlen;
argsNew.data[4] = argsNew.data[2] + 8; // OptData Addr
argsNew.data[4] = dataBufAddr + 8; // OptData Addr
argsNew.data[5] = context->handler.entryPoint; //not part of callback argument, just borrowing a space to store callback address so i don't need to search the context first later
context->eventlock->lock();
context->IsMatchingInCB = true;
context->eventlock->unlock();
// ScheduleEvent_Threadsafe_Immediate seems to get mixed up with interrupt (returning from mipscall inside an interrupt) and getting invalid address before returning from interrupt
__UpdateMatchingHandler(argsNew);
// Make sure MIPS call have been fully executed before the next notifyMatchingHandler
/*int count = 0;
while ( IsMatchingInCallback(context) && (count < 250)) {
sleep_ms(1);
count++;
}
if (count >= 250) ERROR_LOG(SCENET, "MatchingHandler: Callback Failed to Return within %dms! [ID=%i][Opcode=%d][OptSize=%d][MAC=%012X]", count, context->id, msg->opcode, msg->optlen, htonl(*(u_long*)&msg->mac));*/
//sleep_ms(20); // Wait a little more (for context switching may be?) to prevent DBZ Tag Team from getting connection lost, but this will cause lags on Lord of Arcana
}
void freeFriendsRecursive(SceNetAdhocctlPeerInfo * node) {
void freeFriendsRecursive(SceNetAdhocctlPeerInfo * node, int32_t* count) {
// End of List
if (node == NULL) return;
// Increase Recursion Depth
freeFriendsRecursive(node->next);
freeFriendsRecursive(node->next, count);
// Free Memory
free(node);
node = NULL;
if (count != NULL) (*count)++;
}
void timeoutFriendsRecursive(SceNetAdhocctlPeerInfo* node, int32_t* count) {
// End of List
if (node == NULL) return;
// Increase Recursion Depth
timeoutFriendsRecursive(node->next, count);
// Set last timestamp
node->last_recv = 0;
if (count != NULL) (*count)++;
}
void sendChat(std::string chatString) {
@ -1044,6 +1129,7 @@ std::vector<std::string> getChatLog() {
}
int friendFinder(){
setCurrentThreadName("FriendFinder");
// Receive Buffer
int rxpos = 0;
uint8_t rx[1024];
@ -1069,7 +1155,7 @@ int friendFinder(){
//_acquireNetworkLock();
// Ping Server
now = real_time_now()*1000000.0; // should be in microseconds, but it seems real_time_now() returns in seconds
now = real_time_now() * 1000000.0; // CoreTiming::GetGlobalTimeUsScaled(); // Use real_time_now()*1000000.0 if the game gets disconnected from AdhocServer too fast when FPS wasn't stable
if (now - lastping >= PSP_ADHOCCTL_PING_TIMEOUT) { //100 // We need to use lower interval to prevent getting timeout at Pro Adhoc Server through internet
// original code : ((sceKernelGetSystemTimeWide() - lastping) >= ADHOCCTL_PING_TIMEOUT)
// Update Ping Time
@ -1106,18 +1192,33 @@ int friendFinder(){
if (rxpos > 0) {
// BSSID Packet
if (rx[0] == OPCODE_CONNECT_BSSID) {
INFO_LOG(SCENET, "FriendFinder: Incoming OPCODE_CONNECT_BSSID");
// Enough Data available
if (rxpos >= (int)sizeof(SceNetAdhocctlConnectBSSIDPacketS2C)) {
// Cast Packet
SceNetAdhocctlConnectBSSIDPacketS2C * packet = (SceNetAdhocctlConnectBSSIDPacketS2C *)rx;
// Update BSSID
parameter.bssid.mac_addr = packet->mac;
char tmpmac[18];
INFO_LOG(SCENET, "FriendFinder: Incoming OPCODE_CONNECT_BSSID [%s]", mac2str(&packet->mac, tmpmac));
// from JPCSP: Some games have problems when the PSP_ADHOCCTL_EVENT_CONNECTED is sent too quickly after connecting to a network. The connection will be set CONNECTED with a small delay (200ms or 200us?)
/*if (adhocctlCurrentMode == ADHOCCTL_MODE_GAMEMODE) {
setState(ADHOCCTL_STATE_GAMEMODE);
notifyAdhocctlHandlers(ADHOCCTL_EVENT_GAME, 0);
}
else {
setState(ADHOCCTL_STATE_CONNECTED);
notifyAdhocctlHandlers(ADHOCCTL_EVENT_CONNECT, 0);
}*/
// Update User BSSID
//parameter.bssid.mac_addr = packet->mac; // The MAC address in this packet seems to Always be the First player joining the Group (group Creator?), Shouldn't it be it self?
// Notify Event Handlers
//notifyAdhocctlHandlers(ADHOCCTL_EVENT_CONNECT, 0);
// Change State
threadStatus = ADHOCCTL_STATE_CONNECTED;
// Notify Event Handlers
notifyAdhocctlHandlers(ADHOCCTL_EVENT_CONNECT, 0);
// Give time a little time
//sceKernelDelayThread(adhocEventDelayMS * 1000);
//sleep_ms(adhocEventDelayMS);
// Move RX Buffer
memmove(rx, rx + sizeof(SceNetAdhocctlConnectBSSIDPacketS2C), sizeof(rx) - sizeof(SceNetAdhocctlConnectBSSIDPacketS2C));
@ -1128,11 +1229,16 @@ int friendFinder(){
// Chat Packet
else if (rx[0] == OPCODE_CHAT) {
INFO_LOG(SCENET, "FriendFinder: Incoming OPCODE_CHAT");
// Enough Data available
if (rxpos >= (int)sizeof(SceNetAdhocctlChatPacketS2C)) {
// Cast Packet
SceNetAdhocctlChatPacketS2C * packet = (SceNetAdhocctlChatPacketS2C *)rx;
INFO_LOG(SCENET, "FriendFinder: Incoming OPCODE_CHAT");
// Fix strings with null-terminated
packet->name.data[ADHOCCTL_NICKNAME_LEN - 1] = 0;
packet->base.message[ADHOCCTL_MESSAGE_LEN - 1] = 0;
// Add Incoming Chat to HUD
NOTICE_LOG(SCENET, "Received chat message %s", packet->base.message);
incoming = "";
@ -1150,6 +1256,7 @@ int friendFinder(){
newChat += 1;
}
}
// Move RX Buffer
memmove(rx, rx + sizeof(SceNetAdhocctlChatPacketS2C), sizeof(rx) - sizeof(SceNetAdhocctlChatPacketS2C));
@ -1160,17 +1267,28 @@ int friendFinder(){
// Connect Packet
else if (rx[0] == OPCODE_CONNECT) {
DEBUG_LOG(SCENET, "FriendFinder: OPCODE_CONNECT");
// Enough Data available
if (rxpos >= (int)sizeof(SceNetAdhocctlConnectPacketS2C)) {
// Log Incoming Peer
INFO_LOG(SCENET, "Incoming Peer Data...");
// Cast Packet
SceNetAdhocctlConnectPacketS2C * packet = (SceNetAdhocctlConnectPacketS2C *)rx;
DEBUG_LOG(SCENET, "FriendFinder: OPCODE_CONNECT");
// Fix strings with null-terminated
packet->name.data[ADHOCCTL_NICKNAME_LEN - 1] = 0;
// Log Incoming Peer
INFO_LOG(SCENET, "Incoming Peer Data...");
// Add User
addFriend(packet);
/* // Make sure GameMode participants are all joined (including self MAC)
if (adhocctlCurrentMode == PSP_ADHOCCTL_MODE_GAMEMODE) {
// From JPCSP: Join complete when all the required MACs have joined
}*/
// Update HUD User Count
incoming = "";
incoming.append((char *)packet->name.data);
incoming.append(" Joined ");
@ -1181,7 +1299,7 @@ int friendFinder(){
if (chatScreenVisible) {
updateChatScreen = true;
}
// Update HUD User Count
#ifdef LOCALHOST_AS_PEER
setUserCount(getActivePeerCount());
#else
@ -1198,15 +1316,16 @@ int friendFinder(){
// Disconnect Packet
else if (rx[0] == OPCODE_DISCONNECT) {
DEBUG_LOG(SCENET, "FriendFinder: OPCODE_DISCONNECT");
// Enough Data available
if (rxpos >= (int)sizeof(SceNetAdhocctlDisconnectPacketS2C)) {
// Log Incoming Peer Delete Request
INFO_LOG(SCENET, "FriendFinder: Incoming Peer Data Delete Request...");
// Cast Packet
SceNetAdhocctlDisconnectPacketS2C * packet = (SceNetAdhocctlDisconnectPacketS2C *)rx;
DEBUG_LOG(SCENET, "FriendFinder: OPCODE_DISCONNECT");
// Log Incoming Peer Delete Request
INFO_LOG(SCENET, "FriendFinder: Incoming Peer Data Delete Request...");
// Delete User by IP, should delete by MAC since IP can be shared (behind NAT) isn't?
deleteFriendByIP(packet->ip);
@ -1227,14 +1346,16 @@ int friendFinder(){
// Scan Packet
else if (rx[0] == OPCODE_SCAN) {
DEBUG_LOG(SCENET, "FriendFinder: OPCODE_SCAN");
// Enough Data available
if (rxpos >= (int)sizeof(SceNetAdhocctlScanPacketS2C)) {
// Log Incoming Network Information
INFO_LOG(SCENET, "Incoming Group Information...");
// Cast Packet
SceNetAdhocctlScanPacketS2C * packet = (SceNetAdhocctlScanPacketS2C *)rx;
DEBUG_LOG(SCENET, "FriendFinder: OPCODE_SCAN");
// Log Incoming Network Information
INFO_LOG(SCENET, "Incoming Group Information...");
// Multithreading Lock
peerlock.lock();
@ -1242,20 +1363,17 @@ int friendFinder(){
SceNetAdhocctlScanInfo * group = findGroup(&packet->mac);
if (group != NULL) {
// Copy Group Name
group->group_name = packet->group;
// Copy Group Name
group->group_name = packet->group;
// Set Group Host
group->bssid.mac_addr = packet->mac;
}
else
{
// Set Group Host
group->bssid.mac_addr = packet->mac;
} else {
// Allocate Structure Data
SceNetAdhocctlScanInfo * group = (SceNetAdhocctlScanInfo *)malloc(sizeof(SceNetAdhocctlScanInfo));
// Allocated Structure Data
if (group != NULL)
{
if (group != NULL) {
// Clear Memory, should this be done only when allocating new group?
memset(group, 0, sizeof(SceNetAdhocctlScanInfo));
@ -1268,6 +1386,10 @@ int friendFinder(){
// Set Group Host
group->bssid.mac_addr = packet->mac;
// Set group parameters
group->channel = parameter.channel;
group->mode = ADHOCCTL_MODE_ADHOC; //adhocctlCurrentMode;
// Link into Group List
newnetworks = group;
}
@ -1297,16 +1419,18 @@ int friendFinder(){
newnetworks = NULL;
peerlock.unlock();
// Change State
threadStatus = ADHOCCTL_STATE_DISCONNECTED;
// Notify Event Handlers
notifyAdhocctlHandlers(ADHOCCTL_EVENT_SCAN, 0);
//notifyAdhocctlHandlers(ADHOCCTL_EVENT_SCAN, 0);
//int i = 0; for(; i < ADHOCCTL_MAX_HANDLER; i++)
//{
// // Active Handler
// if(_event_handler[i] != NULL) _event_handler[i](ADHOCCTL_EVENT_SCAN, 0, _event_args[i]);
//}
// Change State
threadStatus = ADHOCCTL_STATE_DISCONNECTED;
// Give time a little time
//sceKernelDelayThread(adhocEventDelayMS * 1000);
//sleep_ms(adhocEventDelayMS);
// Move RX Buffer
memmove(rx, rx + 1, sizeof(rx) - 1);
@ -1315,11 +1439,11 @@ int friendFinder(){
rxpos -= 1;
}
}
// Original value was 10 ms, I think 100 is just fine
sleep_ms(1); // Using 1ms for faster response just like AdhocServer
// This delay time should be 100ms when there is an event otherwise 500ms ?
sleep_ms(1); // Using 1ms for faster response just like AdhocServer?
// Don't do anything if it's paused, otherwise the log will be flooded
while (Core_IsStepping() && friendFinderRunning) sleep_ms(1);
while (Core_IsStepping() && coreState != CORE_POWERDOWN && friendFinderRunning) sleep_ms(1);
}
// Groups/Networks should be deallocated isn't?
@ -1334,7 +1458,7 @@ int friendFinder(){
return 0;
}
int getActivePeerCount(void) {
int getActivePeerCount(const bool excludeTimedout) {
// Counter
int count = 0;
@ -1348,8 +1472,9 @@ int getActivePeerCount(void) {
// Iterate Peers
for (; peer != NULL; peer = peer->next) {
// Increase Counter
count++;
// Increase Counter, Should we exclude peers pending for timed out?
if (!excludeTimedout || peer->last_recv != 0)
count++;
}
// Return Result
@ -1365,7 +1490,7 @@ int getLocalIp(sockaddr_in * SocketAddress){
// Error handling
}
// Get local IP addresses
struct hostent *pHost = 0;
struct hostent *pHost = 0;
pHost = ::gethostbyname(szHostName);
if(pHost) {
memcpy(&SocketAddress->sin_addr, pHost->h_addr_list[0], pHost->h_length);
@ -1376,7 +1501,6 @@ int getLocalIp(sockaddr_in * SocketAddress){
}
return -1;
#else
memcpy(&SocketAddress->sin_addr, &localip, sizeof(uint32_t));
char szHostName[256] = "";
gethostname(szHostName, sizeof(szHostName));
struct hostent* pHost = 0;
@ -1388,8 +1512,7 @@ int getLocalIp(sockaddr_in * SocketAddress){
}
return 0;
}
//return -1;
return 0;
return -1;
#endif
}
@ -1468,36 +1591,37 @@ int getNicknameCount(const char * nickname)
* PDP Socket Counter
* @return Number of internal PDP Sockets
*/
int getPDPSocketCount(void)
int getPDPSocketCount()
{
// Socket Counter
int counter = 0;
// Count Sockets
int i = 0; for (; i < 255; i++) if (pdp[i] != NULL) counter++;
for (int i = 0; i < 255; i++) if (pdp[i] != NULL) counter++;
// Return Socket Count
return counter;
}
int getPTPSocketCount(void) {
int getPTPSocketCount() {
// Socket Counter
int counter = 0;
// Count Sockets
int i = 0; for (; i < 255; i++) if (ptp[i] != NULL) counter++;
for (int i = 0; i < 255; i++) if (ptp[i] != NULL) counter++;
// Return Socket Count
return counter;
}
int initNetwork(SceNetAdhocctlAdhocId *adhoc_id){
auto n = GetI18NCategory("Networking");
int iResult = 0;
metasocket = (int)INVALID_SOCKET;
metasocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (metasocket == INVALID_SOCKET){
ERROR_LOG(SCENET, "Invalid socket");
return -1;
return SOCKET_ERROR;
}
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
@ -1512,7 +1636,7 @@ int initNetwork(SceNetAdhocctlAdhocId *adhoc_id){
iResult = getaddrinfo(g_Config.proAdhocServer.c_str(),0,NULL,&resultAddr);
if (iResult != 0) {
ERROR_LOG(SCENET, "DNS Error (%s)\n", g_Config.proAdhocServer.c_str());
host->NotifyUserMessage("DNS Error connecting to " + g_Config.proAdhocServer, 8.0f);
host->NotifyUserMessage(n->T("DNS Error connecting to ") + g_Config.proAdhocServer, 5.0f, 0x0000ff);
return iResult;
}
for (ptr = resultAddr; ptr != NULL; ptr = ptr->ai_next) {
@ -1537,26 +1661,31 @@ int initNetwork(SceNetAdhocctlAdhocId *adhoc_id){
iResult = bind(metasocket, (struct sockaddr*) & localIP, sizeof(sockaddr));
if (iResult == SOCKET_ERROR) {
ERROR_LOG(SCENET, "Bind to alternate localhost[%s] failed(%i).", inet_ntoa(((struct sockaddr_in*) & localIP)->sin_addr), iResult);
host->NotifyUserMessage(std::string(n->T("Failed to Bind Localhost IP")) + " " + inet_ntoa(((struct sockaddr_in*) & localIP)->sin_addr), 3.0, 0x0000ff);
}
}
// Default/Initial Network
memset(&parameter, 0, sizeof(parameter));
strcpy((char *)&parameter.nickname.data, g_Config.sNickName.c_str());
parameter.channel = 1; // Fake Channel 1
parameter.channel = g_Config.iWlanAdhocChannel; // Fake Channel, 0 = Auto where JPCSP use 11 as default for Auto (Commonly for Auto: 1, 6, 11)
if (parameter.channel == PSP_SYSTEMPARAM_ADHOC_CHANNEL_AUTOMATIC) parameter.channel = 1;
getLocalMac(&parameter.bssid.mac_addr);
// Default ProductId
product_code.type = adhoc_id->type;
memcpy(product_code.data, adhoc_id->data, ADHOCCTL_ADHOCID_LEN);
// Connect to Adhoc Server
server_addr.sin_addr = serverIp;
iResult = connect(metasocket,(sockaddr *)&server_addr,sizeof(server_addr));
if (iResult == SOCKET_ERROR) {
uint8_t * sip = (uint8_t *)&server_addr.sin_addr.s_addr;
char buffer[512];
snprintf(buffer, sizeof(buffer), "Socket error (%i) when connecting to %s/%u.%u.%u.%u:%u", errno, g_Config.proAdhocServer.c_str(), sip[0], sip[1], sip[2], sip[3], ntohs(server_addr.sin_port));
snprintf(buffer, sizeof(buffer), "Socket error (%i) when connecting to AdhocServer [%s/%s:%u]", errno, g_Config.proAdhocServer.c_str(), inet_ntoa(server_addr.sin_addr), ntohs(server_addr.sin_port));
ERROR_LOG(SCENET, "%s", buffer);
host->NotifyUserMessage(buffer, 8.0f);
host->NotifyUserMessage(buffer, 5.0f, 0x0000ff);
return iResult;
}
//grab local ip for later use better than constant ip on non windows platform
localip = getLocalIp(metasocket);
// Prepare Login Packet
SceNetAdhocctlLoginPacketC2S packet;
@ -1569,12 +1698,11 @@ int initNetwork(SceNetAdhocctlAdhocId *adhoc_id){
int sent = send(metasocket, (char*)&packet, sizeof(packet), 0);
changeBlockingMode(metasocket, 1); // Change to non-blocking
if (sent > 0) {
auto n = GetI18NCategory("Networking");
host->NotifyUserMessage(n->T("Network Initialized"), 1.0);
return 0;
}
else{
return -1;
return SOCKET_ERROR;
}
}
@ -1665,7 +1793,7 @@ bool validNetworkName(const SceNetAdhocctlGroupName * group_name) {
// Name given
if (group_name != NULL) {
// Iterate Name Characters
int i = 0; for (; i < ADHOCCTL_GROUPNAME_LEN && valid; i++) {
for (int i = 0; i < ADHOCCTL_GROUPNAME_LEN && valid; i++) {
// End of Name
if (group_name->data[i] == 0) break;

View file

@ -27,6 +27,7 @@
#include "Core/CoreTiming.h"
#include "Core/MemMap.h"
#include "Core/HLE/HLE.h"
#include "Core/HLE/HLEHelperThread.h"
#include "Core/HLE/sceNetAdhoc.h"
#include "Core/HLE/sceKernelThread.h"
#include "Core/HLE/sceKernel.h"
@ -73,7 +74,7 @@ class PointerWrap;
#define EINPROGRESS WSAEWOULDBLOCK
#define EISCONN WSAEISCONN
#define EALREADY WSAEALREADY
inline bool connectInProgress(int errcode){ return (errcode == WSAEWOULDBLOCK || errcode == WSAEINVAL || errcode == WSAEALREADY); }
inline bool connectInProgress(int errcode){ return (errcode == WSAEWOULDBLOCK || errcode == WSAEINPROGRESS || errcode == WSAEALREADY); }
#else
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
@ -101,19 +102,32 @@ inline bool connectInProgress(int errcode){ return (errcode == EINPROGRESS || er
#define SERVER_PORT 27312
// psp strutcs and definitions
#define ADHOCCTL_MODE_ADHOC 0
#define ADHOCCTL_MODE_NONE -1
#define ADHOCCTL_MODE_ADHOC 0 //ADHOCCTL_MODE_NORMAL
#define ADHOCCTL_MODE_GAMEMODE 1
// Event Types for Event Handler
#define ADHOCCTL_EVENT_ERROR 0
#define ADHOCCTL_EVENT_CONNECT 1
#define ADHOCCTL_EVENT_DISCONNECT 2
#define ADHOCCTL_EVENT_SCAN 3
#define ADHOCCTL_EVENT_GAME 4
#define ADHOCCTL_EVENT_DISCOVER 5
#define ADHOCCTL_EVENT_WOL 6
#define ADHOCCTL_EVENT_WOL_INTERRUPT 7
// Internal Thread States
#define ADHOCCTL_STATE_DISCONNECTED 0
#define ADHOCCTL_STATE_CONNECTED 1
#define ADHOCCTL_STATE_SCANNING 2
#define ADHOCCTL_STATE_GAMEMODE 3
#define ADHOCCTL_STATE_DISCOVER 4
#define ADHOCCTL_STATE_WOL 5
// ProductType ( extracted from SSID along with ProductId & GroupName, Pattern = "PSP_([AXS])(.........)_([LG])_(.*)" )
#define PSP_ADHOCCTL_TYPE_COMMERCIAL 0
#define PSP_ADHOCCTL_TYPE_DEBUG 1
#define PSP_ADHOCCTL_TYPE_SYSTEM 2
// Kernel Utility Netconf Adhoc Types
#define UTILITY_NETCONF_TYPE_CONNECT_ADHOC 2
@ -186,8 +200,8 @@ extern uint8_t broadcastMAC[ETHER_ADDR_LEN];
// Malloc Pool Information
typedef struct SceNetMallocStat {
s32_le pool; // Pointer to the pool?
s32_le maximum; // Maximum size of the pool?
s32_le pool; // Pointer to the pool? // This should be the poolSize isn't?
s32_le maximum; // Maximum size of the pool? Maximum usage (ie. pool- free) ?
s32_le free; // How much memory is free
} PACK SceNetMallocStat;
@ -321,9 +335,6 @@ typedef struct SceNetAdhocGameModeBufferStat {
u32_le master;
SceNetAdhocGameModeOptData opt;
} PACK SceNetAdhocGameModeBufferStat;
#ifdef _MSC_VER
#pragma pack(pop)
#endif
// Adhoc ID (Game Product Key)
#define ADHOCCTL_ADHOCID_LEN 9
@ -331,7 +342,11 @@ typedef struct SceNetAdhocctlAdhocId {
s32_le type;
uint8_t data[ADHOCCTL_ADHOCID_LEN];
uint8_t padding[3];
} SceNetAdhocctlAdhocId; // should this be packed?
} PACK SceNetAdhocctlAdhocId; // should this be packed?
#ifdef _MSC_VER
#pragma pack(pop)
#endif
// Internal Matching Peer Information
typedef struct SceNetAdhocMatchingMemberInternal {
@ -459,8 +474,8 @@ typedef struct SceNetAdhocMatchingContext {
u64_le timeout;
// Helper Thread (fake PSP Thread) needed to execute callback
//HLEHelperThread *matchingThread;
//SceUID matching_thid;
HLEHelperThread *matchingThread;
SceUID matching_thid;
// Event Caller Thread
std::thread eventThread; // s32_le event_thid;
@ -704,10 +719,11 @@ typedef struct {
SceNetAdhocctlGroupName group;
} PACK SceNetAdhocctlConnectPacketC2S;
#define ADHOCCTL_MESSAGE_LEN 64
// C2S Chat Packet
typedef struct {
SceNetAdhocctlPacketBase base;
char message[64];
char message[ADHOCCTL_MESSAGE_LEN];
} PACK SceNetAdhocctlChatPacketC2S;
// S2C Connect Packet
@ -763,30 +779,56 @@ typedef struct {
#pragma pack(pop)
#endif
class AfterAdhocMipsCall : public PSPAction {
public:
AfterAdhocMipsCall() {}
static PSPAction* Create() { return new AfterAdhocMipsCall(); }
void DoState(PointerWrap& p) override {
auto s = p.Section("AfterAdhocMipsCall", 4, 4);
if (!s)
return;
p.Do(HandlerID);
p.Do(EventID);
p.Do(argsAddr);
}
void run(MipsCall& call) override;
void SetData(int handlerID, int eventId, u32_le argsAddr);
private:
int HandlerID = -1;
int EventID = -1;
u32_le argsAddr = 0;
};
class AfterMatchingMipsCall : public PSPAction {
public:
AfterMatchingMipsCall() {}
static PSPAction *Create() { return new AfterMatchingMipsCall(); }
void DoState(PointerWrap &p) override {
auto s = p.Section("AfterMatchingMipsCall", 1, 2);
auto s = p.Section("AfterMatchingMipsCall", 1, 4);
if (!s)
return;
p.Do(EventID);
if (s >= 4) {
p.Do(contextID);
p.Do(bufAddr);
}
//context = NULL;
}
void run(MipsCall &call) override;
void SetContextID(u32 ContextID, u32 eventId, u32_le BufAddr);
void SetContext(SceNetAdhocMatchingContext* Context, u32 eventId, u32_le BufAddr) { context = Context; EventID = eventId; bufAddr = BufAddr; }
void SetData(int ContextID, int eventId, u32_le BufAddr);
private:
u32 EventID = 0;
SceNetAdhocMatchingContext *context = nullptr;
int contextID = -1;
int EventID = -1;
u32_le bufAddr = 0;
SceNetAdhocMatchingContext* context = nullptr;
};
extern int actionAfterAdhocMipsCall;
extern int actionAfterMatchingMipsCall;
extern bool IsAdhocctlInCB;
// Aux vars
extern int metasocket;
@ -796,7 +838,6 @@ extern std::thread friendFinderThread;
extern std::recursive_mutex peerlock;
extern SceNetAdhocPdpStat * pdp[255];
extern SceNetAdhocPtpStat * ptp[255];
extern std::map<int, AdhocctlHandler> adhocctlHandlers;
extern uint16_t portOffset;
extern bool isLocalServer;
@ -812,27 +853,34 @@ extern int threadStatus;
// Check if Matching callback is running
bool IsMatchingInCallback(SceNetAdhocMatchingContext * context);
bool SetMatchingInCallback(SceNetAdhocMatchingContext* context, bool IsInCB);
int IsAdhocctlInCallback();
int SetAdhocctlInCallback(bool IsInCB);
/**
* Local MAC Check
* @param saddr To-be-checked MAC Address
* @return 1 if valid or... 0
*/
int isLocalMAC(const SceNetEtherAddr * addr);
bool isLocalMAC(const SceNetEtherAddr * addr);
/**
* PDP Port Check
* @param port To-be-checked Port
* @return 1 if in use or... 0
*/
int isPDPPortInUse(uint16_t port);
bool isPDPPortInUse(uint16_t port);
/**
* Check whether PTP Port is in use or not
* @param port To-be-checked Port Number
* @return 1 if in use or... 0
*/
int isPTPPortInUse(uint16_t port);
bool isPTPPortInUse(uint16_t port);
char* mac2str(SceNetEtherAddr* mac);
char* mac2str(SceNetEtherAddr* mac, char* str, size_t size = 18);
/*
* Matching Members
@ -890,12 +938,12 @@ void freeGroupsRecursive(SceNetAdhocctlScanInfo * node);
/**
* Closes & Deletes all PDP Sockets
*/
void deleteAllPDP(void);
void deleteAllPDP();
/**
* Closes & Deletes all PTP sockets
*/
void deleteAllPTP(void);
void deleteAllPTP();
/**
* Delete Friend from Local List
@ -907,7 +955,9 @@ void deleteFriendByIP(uint32_t ip);
* Recursive Memory Freeing-Helper for Friend-Structures
* @param node Current Node in List
*/
void freeFriendsRecursive(SceNetAdhocctlPeerInfo * node);
void freeFriendsRecursive(SceNetAdhocctlPeerInfo * node, int32_t* count);
void timeoutFriendsRecursive(SceNetAdhocctlPeerInfo* node, int32_t* count);
/**
* Friend Finder Thread (Receives Peer Information)
@ -921,7 +971,7 @@ int friendFinder();
* Find Free Matching ID
* @return First unoccupied Matching ID
*/
int findFreeMatchingID(void);
int findFreeMatchingID();
/**
* Find Internal Matching Context for Matching ID
@ -933,7 +983,7 @@ SceNetAdhocMatchingContext * findMatchingContext(int id);
/*
* Notify Matching Event Handler
*/
void notifyMatchingHandler(SceNetAdhocMatchingContext * context, ThreadMessage * msg, void * opt, u32 &bufAddr, u32 &bufLen, u32_le * args);
void notifyMatchingHandler(SceNetAdhocMatchingContext * context, ThreadMessage * msg, void * opt, u32_le &bufAddr, u32_le &bufLen, u32_le * args);
// Notifiy Adhocctl Handlers
void notifyAdhocctlHandlers(u32 flag, u32 error);
@ -1030,7 +1080,7 @@ void sendDeathMessage(SceNetAdhocMatchingContext * context, SceNetAdhocMatchingM
* @param context Matching Context Pointer
* @return Number of Children
*/
s32_le countChildren(SceNetAdhocMatchingContext * context);
s32_le countChildren(SceNetAdhocMatchingContext * context, const bool excludeTimedout = false);
/**
* Delete Peer from List
@ -1059,14 +1109,14 @@ SceNetAdhocMatchingMemberInternal * findParent(SceNetAdhocMatchingContext * cont
* @param context Matching Context Pointer
* @return Internal Peer Reference or... NULL
*/
SceNetAdhocMatchingMemberInternal * findP2P(SceNetAdhocMatchingContext * context);
SceNetAdhocMatchingMemberInternal * findP2P(SceNetAdhocMatchingContext * context, const bool excludeTimedout = false);
/**
* Return Number of Connected Peers
* @param context Matching Context Pointer
* @return Number of Connected Peers
*/
uint32_t countConnectedPeers(SceNetAdhocMatchingContext * context);
uint32_t countConnectedPeers(SceNetAdhocMatchingContext * context, const bool excludeTimedout = false);
/**
* Spawn Local Event for Event Thread
@ -1093,7 +1143,7 @@ void spawnLocalEvent(SceNetAdhocMatchingContext * context, int event, SceNetEthe
* Return Number of active Peers in the same Network as the Local Player
* @return Number of active Peers
*/
int getActivePeerCount(void);
int getActivePeerCount(const bool excludeTimedout = true);
/**
* Returns the locall Ip of this machine, TODO: Implement the linux version
@ -1152,13 +1202,13 @@ uint16_t getLocalPort(int sock);
* PDP Socket Counter
* @return Number of internal PDP Sockets
*/
int getPDPSocketCount(void);
int getPDPSocketCount();
/**
* PTP Socket Counter
* @return Number of internal PTP Sockets
*/
int getPTPSocketCount(void);
int getPTPSocketCount();
/**
* Initialize Networking Components for Adhocctl Emulator

View file

@ -42,9 +42,12 @@
#include <fcntl.h>
#include <errno.h>
//#include <sqlite3.h>
#include "thread/threadutil.h"
#include "Common/FileUtil.h"
#include "Core/Core.h"
#include "Core/Host.h"
#include "Core/HLE/proAdhocServer.h"
#include "i18n/i18n.h"
// User Count
@ -497,8 +500,7 @@ void login_user_stream(int fd, uint32_t ip)
while(u != NULL && u->resolver.ip != ip) u = u->next;
if (u != NULL) { // IP Already existed
uint8_t * ip4 = (uint8_t *)&u->resolver.ip;
WARN_LOG(SCENET, "AdhocServer: Already Existing IP: %u.%u.%u.%u\n", ip4[0], ip4[1], ip4[2], ip4[3]);
WARN_LOG(SCENET, "AdhocServer: Already Existing IP: %s\n", inet_ntoa(*(in_addr*)&u->resolver.ip));
}
// Unique IP Address
@ -528,8 +530,7 @@ void login_user_stream(int fd, uint32_t ip)
user->last_recv = time(NULL);
// Notify User
uint8_t * ipa = (uint8_t *)&user->resolver.ip;
INFO_LOG(SCENET, "AdhocServer: New Connection from %u.%u.%u.%u", ipa[0], ipa[1], ipa[2], ipa[3]);
INFO_LOG(SCENET, "AdhocServer: New Connection from %s", inet_ntoa(*(in_addr*)&user->resolver.ip));
// Fix User Counter
_db_user_count++;
@ -572,8 +573,7 @@ void login_user_data(SceNetAdhocctlUserNode * user, SceNetAdhocctlLoginPacketC2S
while (u != NULL && !IsMatch(u->resolver.mac, data->mac)) u = u->next;
if (u != NULL) { // MAC Already existed
uint8_t* ip4 = (uint8_t*)&u->resolver.ip;
WARN_LOG(SCENET, "AdhocServer: Already Existing MAC: %02X:%02X:%02X:%02X:%02X:%02X [%u.%u.%u.%u]\n", data->mac.data[0], data->mac.data[1], data->mac.data[2], data->mac.data[3], data->mac.data[4], data->mac.data[5], ip4[0], ip4[1], ip4[2], ip4[3]);
WARN_LOG(SCENET, "AdhocServer: Already Existing MAC: %02x:%02x:%02x:%02x:%02x:%02x [%s]\n", data->mac.data[0], data->mac.data[1], data->mac.data[2], data->mac.data[3], data->mac.data[4], data->mac.data[5], inet_ntoa(*(in_addr*)&u->resolver.ip));
}
// Game Product Override
@ -621,11 +621,10 @@ void login_user_data(SceNetAdhocctlUserNode * user, SceNetAdhocctlLoginPacketC2S
user->game = game;
// Notify User
uint8_t * ip = (uint8_t *)&user->resolver.ip;
char safegamestr[10];
memset(safegamestr, 0, sizeof(safegamestr));
strncpy(safegamestr, game->game.data, PRODUCT_CODE_LENGTH);
INFO_LOG(SCENET, "AdhocServer: %s (MAC: %02X:%02X:%02X:%02X:%02X:%02X - IP: %u.%u.%u.%u) started playing %s", (char *)user->resolver.name.data, user->resolver.mac.data[0], user->resolver.mac.data[1], user->resolver.mac.data[2], user->resolver.mac.data[3], user->resolver.mac.data[4], user->resolver.mac.data[5], ip[0], ip[1], ip[2], ip[3], safegamestr);
INFO_LOG(SCENET, "AdhocServer: %s (MAC: %02x:%02x:%02x:%02x:%02x:%02x - IP: %s) started playing %s", (char *)user->resolver.name.data, user->resolver.mac.data[0], user->resolver.mac.data[1], user->resolver.mac.data[2], user->resolver.mac.data[3], user->resolver.mac.data[4], user->resolver.mac.data[5], inet_ntoa(*(in_addr*)&user->resolver.ip), safegamestr);
// Update Status Log
update_status();
@ -639,8 +638,7 @@ void login_user_data(SceNetAdhocctlUserNode * user, SceNetAdhocctlLoginPacketC2S
else
{
// Notify User
uint8_t * ip = (uint8_t *)&user->resolver.ip;
WARN_LOG(SCENET, "AdhocServer: Invalid Login Packet Contents from %u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
WARN_LOG(SCENET, "AdhocServer: Invalid Login Packet Contents from %s", inet_ntoa(*(in_addr*)&user->resolver.ip));
}
// Logout User - Out of Memory or Invalid Arguments
@ -672,11 +670,10 @@ void logout_user(SceNetAdhocctlUserNode * user)
if(user->game != NULL)
{
// Notify User
uint8_t * ip = (uint8_t *)&user->resolver.ip;
char safegamestr[10];
memset(safegamestr, 0, sizeof(safegamestr));
strncpy(safegamestr, user->game->game.data, PRODUCT_CODE_LENGTH);
INFO_LOG(SCENET, "AdhocServer: %s (MAC: %02X:%02X:%02X:%02X:%02X:%02X - IP: %u.%u.%u.%u) stopped playing %s", (char *)user->resolver.name.data, user->resolver.mac.data[0], user->resolver.mac.data[1], user->resolver.mac.data[2], user->resolver.mac.data[3], user->resolver.mac.data[4], user->resolver.mac.data[5], ip[0], ip[1], ip[2], ip[3], safegamestr);
INFO_LOG(SCENET, "AdhocServer: %s (MAC: %02x:%02x:%02x:%02x:%02x:%02x - IP: %s) stopped playing %s", (char *)user->resolver.name.data, user->resolver.mac.data[0], user->resolver.mac.data[1], user->resolver.mac.data[2], user->resolver.mac.data[3], user->resolver.mac.data[4], user->resolver.mac.data[5], inet_ntoa(*(in_addr*)&user->resolver.ip), safegamestr);
// Fix Game Player Count
user->game->playercount--;
@ -702,8 +699,7 @@ void logout_user(SceNetAdhocctlUserNode * user)
else
{
// Notify User
uint8_t * ip = (uint8_t *)&user->resolver.ip;
WARN_LOG(SCENET, "AdhocServer: Dropped Connection to %u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
WARN_LOG(SCENET, "AdhocServer: Dropped Connection to %s", inet_ntoa(*(in_addr*)&user->resolver.ip));
}
// Free Memory
@ -719,7 +715,7 @@ void logout_user(SceNetAdhocctlUserNode * user)
/**
* Free Database Memory
*/
void free_database(void)
void free_database()
{
// There are users playing
if(_db_user_count > 0)
@ -885,14 +881,13 @@ void connect_user(SceNetAdhocctlUserNode * user, SceNetAdhocctlGroupName * group
if (iResult < 0) ERROR_LOG(SCENET, "AdhocServer: connect_user[send user bssid] (Socket error %d)", errno);
// Notify User
uint8_t * ip = (uint8_t *)&user->resolver.ip;
char safegamestr[10];
memset(safegamestr, 0, sizeof(safegamestr));
strncpy(safegamestr, user->game->game.data, PRODUCT_CODE_LENGTH);
char safegroupstr[9];
memset(safegroupstr, 0, sizeof(safegroupstr));
strncpy(safegroupstr, (char *)user->group->group.data, ADHOCCTL_GROUPNAME_LEN);
INFO_LOG(SCENET, "AdhocServer: %s (MAC: %02X:%02X:%02X:%02X:%02X:%02X - IP: %u.%u.%u.%u) joined %s group %s", (char *)user->resolver.name.data, user->resolver.mac.data[0], user->resolver.mac.data[1], user->resolver.mac.data[2], user->resolver.mac.data[3], user->resolver.mac.data[4], user->resolver.mac.data[5], ip[0], ip[1], ip[2], ip[3], safegamestr, safegroupstr);
INFO_LOG(SCENET, "AdhocServer: %s (MAC: %02x:%02x:%02x:%02x:%02x:%02x - IP: %s) joined %s group %s", (char *)user->resolver.name.data, user->resolver.mac.data[0], user->resolver.mac.data[1], user->resolver.mac.data[2], user->resolver.mac.data[3], user->resolver.mac.data[4], user->resolver.mac.data[5], inet_ntoa(*(in_addr*)&user->resolver.ip), safegamestr, safegroupstr);
// Update Status Log
update_status();
@ -906,7 +901,6 @@ void connect_user(SceNetAdhocctlUserNode * user, SceNetAdhocctlGroupName * group
else
{
// Notify User
uint8_t * ip = (uint8_t *)&user->resolver.ip;
char safegamestr[10];
memset(safegamestr, 0, sizeof(safegamestr));
strncpy(safegamestr, user->game->game.data, PRODUCT_CODE_LENGTH);
@ -916,7 +910,7 @@ void connect_user(SceNetAdhocctlUserNode * user, SceNetAdhocctlGroupName * group
char safegroupstr2[9];
memset(safegroupstr2, 0, sizeof(safegroupstr2));
strncpy(safegroupstr2, (char *)user->group->group.data, ADHOCCTL_GROUPNAME_LEN);
WARN_LOG(SCENET, "AdhocServer: %s (MAC: %02X:%02X:%02X:%02X:%02X:%02X - IP: %u.%u.%u.%u) attempted to join %s group %s without disconnecting from %s first", (char *)user->resolver.name.data, user->resolver.mac.data[0], user->resolver.mac.data[1], user->resolver.mac.data[2], user->resolver.mac.data[3], user->resolver.mac.data[4], user->resolver.mac.data[5], ip[0], ip[1], ip[2], ip[3], safegamestr, safegroupstr, safegroupstr2);
WARN_LOG(SCENET, "AdhocServer: %s (MAC: %02x:%02x:%02x:%02x:%02x:%02x - IP: %s) attempted to join %s group %s without disconnecting from %s first", (char *)user->resolver.name.data, user->resolver.mac.data[0], user->resolver.mac.data[1], user->resolver.mac.data[2], user->resolver.mac.data[3], user->resolver.mac.data[4], user->resolver.mac.data[5], inet_ntoa(*(in_addr*)&user->resolver.ip), safegamestr, safegroupstr, safegroupstr2);
}
}
@ -924,14 +918,13 @@ void connect_user(SceNetAdhocctlUserNode * user, SceNetAdhocctlGroupName * group
else
{
// Notify User
uint8_t * ip = (uint8_t *)&user->resolver.ip;
char safegamestr[10];
memset(safegamestr, 0, sizeof(safegamestr));
strncpy(safegamestr, user->game->game.data, PRODUCT_CODE_LENGTH);
char safegroupstr[9];
memset(safegroupstr, 0, sizeof(safegroupstr));
strncpy(safegroupstr, (char *)group->data, ADHOCCTL_GROUPNAME_LEN);
WARN_LOG(SCENET, "AdhocServer: %s (MAC: %02X:%02X:%02X:%02X:%02X:%02X - IP: %u.%u.%u.%u) attempted to join invalid %s group %s", (char *)user->resolver.name.data, user->resolver.mac.data[0], user->resolver.mac.data[1], user->resolver.mac.data[2], user->resolver.mac.data[3], user->resolver.mac.data[4], user->resolver.mac.data[5], ip[0], ip[1], ip[2], ip[3], safegamestr, safegroupstr);
WARN_LOG(SCENET, "AdhocServer: %s (MAC: %02x:%02x:%02x:%02x:%02x:%02x - IP: %s) attempted to join invalid %s group %s", (char *)user->resolver.name.data, user->resolver.mac.data[0], user->resolver.mac.data[1], user->resolver.mac.data[2], user->resolver.mac.data[3], user->resolver.mac.data[4], user->resolver.mac.data[5], inet_ntoa(*(in_addr*)&user->resolver.ip), safegamestr, safegroupstr);
}
// Invalid State, Out of Memory or Invalid Group Name
@ -984,14 +977,13 @@ void disconnect_user(SceNetAdhocctlUserNode * user)
}
// Notify User
uint8_t * ip = (uint8_t *)&user->resolver.ip;
char safegamestr[10];
memset(safegamestr, 0, sizeof(safegamestr));
strncpy(safegamestr, user->game->game.data, PRODUCT_CODE_LENGTH);
char safegroupstr[9];
memset(safegroupstr, 0, sizeof(safegroupstr));
strncpy(safegroupstr, (char *)user->group->group.data, ADHOCCTL_GROUPNAME_LEN);
INFO_LOG(SCENET, "AdhocServer: %s (MAC: %02X:%02X:%02X:%02X:%02X:%02X - IP: %u.%u.%u.%u) left %s group %s", (char *)user->resolver.name.data, user->resolver.mac.data[0], user->resolver.mac.data[1], user->resolver.mac.data[2], user->resolver.mac.data[3], user->resolver.mac.data[4], user->resolver.mac.data[5], ip[0], ip[1], ip[2], ip[3], safegamestr, safegroupstr);
INFO_LOG(SCENET, "AdhocServer: %s (MAC: %02x:%02x:%02x:%02x:%02x:%02x - IP: %s) left %s group %s", (char *)user->resolver.name.data, user->resolver.mac.data[0], user->resolver.mac.data[1], user->resolver.mac.data[2], user->resolver.mac.data[3], user->resolver.mac.data[4], user->resolver.mac.data[5], inet_ntoa(*(in_addr*)&user->resolver.ip), safegamestr, safegroupstr);
// Empty Group
if(user->group->playercount == 0)
@ -1028,11 +1020,10 @@ void disconnect_user(SceNetAdhocctlUserNode * user)
else
{
// Notify User
uint8_t * ip = (uint8_t *)&user->resolver.ip;
char safegamestr[10];
memset(safegamestr, 0, sizeof(safegamestr));
strncpy(safegamestr, user->game->game.data, PRODUCT_CODE_LENGTH);
WARN_LOG(SCENET, "AdhocServer: %s (MAC: %02X:%02X:%02X:%02X:%02X:%02X - IP: %u.%u.%u.%u) attempted to leave %s group without joining one first", (char *)user->resolver.name.data, user->resolver.mac.data[0], user->resolver.mac.data[1], user->resolver.mac.data[2], user->resolver.mac.data[3], user->resolver.mac.data[4], user->resolver.mac.data[5], ip[0], ip[1], ip[2], ip[3], safegamestr);
WARN_LOG(SCENET, "AdhocServer: %s (MAC: %02x:%02x:%02x:%02x:%02x:%02x - IP: %s) attempted to leave %s group without joining one first", (char *)user->resolver.name.data, user->resolver.mac.data[0], user->resolver.mac.data[1], user->resolver.mac.data[2], user->resolver.mac.data[3], user->resolver.mac.data[4], user->resolver.mac.data[5], inet_ntoa(*(in_addr*)&user->resolver.ip), safegamestr);
}
// Delete User
@ -1087,11 +1078,10 @@ void send_scan_results(SceNetAdhocctlUserNode * user)
if (iResult < 0) ERROR_LOG(SCENET, "AdhocServer: send_scan_result[send peer complete] (Socket error %d)", errno);
// Notify User
uint8_t * ip = (uint8_t *)&user->resolver.ip;
char safegamestr[10];
memset(safegamestr, 0, sizeof(safegamestr));
strncpy(safegamestr, user->game->game.data, PRODUCT_CODE_LENGTH);
INFO_LOG(SCENET, "AdhocServer: %s (MAC: %02X:%02X:%02X:%02X:%02X:%02X - IP: %u.%u.%u.%u) requested information on %d %s groups", (char *)user->resolver.name.data, user->resolver.mac.data[0], user->resolver.mac.data[1], user->resolver.mac.data[2], user->resolver.mac.data[3], user->resolver.mac.data[4], user->resolver.mac.data[5], ip[0], ip[1], ip[2], ip[3], user->game->groupcount, safegamestr);
INFO_LOG(SCENET, "AdhocServer: %s (MAC: %02x:%02x:%02x:%02x:%02x:%02x - IP: %s) requested information on %d %s groups", (char *)user->resolver.name.data, user->resolver.mac.data[0], user->resolver.mac.data[1], user->resolver.mac.data[2], user->resolver.mac.data[3], user->resolver.mac.data[4], user->resolver.mac.data[5], inet_ntoa(*(in_addr*)&user->resolver.ip), user->game->groupcount, safegamestr);
// Exit Function
return;
@ -1101,14 +1091,13 @@ void send_scan_results(SceNetAdhocctlUserNode * user)
else
{
// Notify User
uint8_t * ip = (uint8_t *)&user->resolver.ip;
char safegamestr[10];
memset(safegamestr, 0, sizeof(safegamestr));
strncpy(safegamestr, user->game->game.data, PRODUCT_CODE_LENGTH);
char safegroupstr[9];
memset(safegroupstr, 0, sizeof(safegroupstr));
strncpy(safegroupstr, (char *)user->group->group.data, ADHOCCTL_GROUPNAME_LEN);
WARN_LOG(SCENET, "AdhocServer: %s (MAC: %02X:%02X:%02X:%02X:%02X:%02X - IP: %u.%u.%u.%u) attempted to scan for %s groups without disconnecting from %s first", (char *)user->resolver.name.data, user->resolver.mac.data[0], user->resolver.mac.data[1], user->resolver.mac.data[2], user->resolver.mac.data[3], user->resolver.mac.data[4], user->resolver.mac.data[5], ip[0], ip[1], ip[2], ip[3], safegamestr, safegroupstr);
WARN_LOG(SCENET, "AdhocServer: %s (MAC: %02x:%02x:%02x:%02x:%02x:%02x - IP: %s) attempted to scan for %s groups without disconnecting from %s first", (char *)user->resolver.name.data, user->resolver.mac.data[0], user->resolver.mac.data[1], user->resolver.mac.data[2], user->resolver.mac.data[3], user->resolver.mac.data[4], user->resolver.mac.data[5], inet_ntoa(*(in_addr*)&user->resolver.ip), safegamestr, safegroupstr);
}
// Delete User
@ -1200,14 +1189,13 @@ void spread_message(SceNetAdhocctlUserNode *user, const char *message)
if(counter > 0)
{
// Notify User
uint8_t * ip = (uint8_t *)&user->resolver.ip;
char safegamestr[10];
memset(safegamestr, 0, sizeof(safegamestr));
strncpy(safegamestr, user->game->game.data, PRODUCT_CODE_LENGTH);
char safegroupstr[9];
memset(safegroupstr, 0, sizeof(safegroupstr));
strncpy(safegroupstr, (char *)user->group->group.data, ADHOCCTL_GROUPNAME_LEN);
INFO_LOG(SCENET, "AdhocServer: %s (MAC: %02X:%02X:%02X:%02X:%02X:%02X - IP: %u.%u.%u.%u) sent \"%s\" to %d players in %s group %s", (char *)user->resolver.name.data, user->resolver.mac.data[0], user->resolver.mac.data[1], user->resolver.mac.data[2], user->resolver.mac.data[3], user->resolver.mac.data[4], user->resolver.mac.data[5], ip[0], ip[1], ip[2], ip[3], message, counter, safegamestr, safegroupstr);
INFO_LOG(SCENET, "AdhocServer: %s (MAC: %02x:%02x:%02x:%02x:%02x:%02x - IP: %s) sent \"%s\" to %d players in %s group %s", (char *)user->resolver.name.data, user->resolver.mac.data[0], user->resolver.mac.data[1], user->resolver.mac.data[2], user->resolver.mac.data[3], user->resolver.mac.data[4], user->resolver.mac.data[5], inet_ntoa(*(in_addr*)&user->resolver.ip), message, counter, safegamestr, safegroupstr);
}
// Exit Function
@ -1218,11 +1206,10 @@ void spread_message(SceNetAdhocctlUserNode *user, const char *message)
else
{
// Notify User
uint8_t * ip = (uint8_t *)&user->resolver.ip;
char safegamestr[10];
memset(safegamestr, 0, sizeof(safegamestr));
strncpy(safegamestr, user->game->game.data, PRODUCT_CODE_LENGTH);
WARN_LOG(SCENET, "AdhocServer: %s (MAC: %02X:%02X:%02X:%02X:%02X:%02X - IP: %u.%u.%u.%u) attempted to send a text message without joining a %s group first", (char *)user->resolver.name.data, user->resolver.mac.data[0], user->resolver.mac.data[1], user->resolver.mac.data[2], user->resolver.mac.data[3], user->resolver.mac.data[4], user->resolver.mac.data[5], ip[0], ip[1], ip[2], ip[3], safegamestr);
WARN_LOG(SCENET, "AdhocServer: %s (MAC: %02x:%02x:%02x:%02x:%02x:%02x - IP: %s) attempted to send a text message without joining a %s group first", (char *)user->resolver.name.data, user->resolver.mac.data[0], user->resolver.mac.data[1], user->resolver.mac.data[2], user->resolver.mac.data[3], user->resolver.mac.data[4], user->resolver.mac.data[5], inet_ntoa(*(in_addr*)&user->resolver.ip), safegamestr);
}
// Delete User
@ -1417,7 +1404,7 @@ void game_product_override(SceNetAdhocctlProductCode * product)
/**
* Update Status Logfile
*/
void update_status(void)
void update_status()
{
// Open Logfile
FILE * log = File::OpenCFile(SERVER_STATUS_XMLOUT, "w");
@ -1672,6 +1659,7 @@ const char * strcpyxml(char * out, const char * in, uint32_t size)
*/
int proAdhocServerThread(int port) // (int argc, char * argv[])
{
setCurrentThreadName("AdhocServer");
// Result
int result = 0;
@ -1806,7 +1794,7 @@ int create_listen_socket(uint16_t port)
int bindresult = bind(fd, (struct sockaddr *)&local, sizeof(local));
// Bound Local Address to Socket
if(bindresult != -1)
if(bindresult != SOCKET_ERROR)
{
// Switch Socket into Listening Mode
listen(fd, SERVER_LISTEN_BACKLOG);
@ -1816,7 +1804,11 @@ int create_listen_socket(uint16_t port)
}
// Notify User
else ERROR_LOG(SCENET, "AdhocServer: Bind returned %i (Socket error %d)", bindresult, errno);
else {
ERROR_LOG(SCENET, "AdhocServer: Bind returned %i (Socket error %d)", bindresult, errno);
I18NCategory* n = GetI18NCategory("Networking");
host->NotifyUserMessage(std::string(n->T("AdhocServer Failed to Bind Port")) + " " + std::to_string(port), 3.0, 0x0000ff);
}
// Close Socket
closesocket(fd);
@ -1880,7 +1872,7 @@ int server_loop(int server)
u8 *pip = (u8*)&sip;
if (gethostbyname(str)->h_addrtype == AF_INET && gethostbyname(str)->h_addr_list[0] != NULL) pip = (u8*)gethostbyname(str)->h_addr_list[0];
sip = *(u32_le*)pip;
WARN_LOG(SCENET, "AdhocServer: Replacing IP %s with %u.%u.%u.%u", inet_ntoa(addr.sin_addr), pip[0], pip[1], pip[2], pip[3]);
WARN_LOG(SCENET, "AdhocServer: Replacing IP %s with %s", inet_ntoa(addr.sin_addr), inet_ntoa(*(in_addr*)&pip));
}
*/
login_user_stream(loginresult, sip);
@ -1942,8 +1934,7 @@ int server_loop(int server)
else
{
// Notify User
uint8_t * ip = (uint8_t *)&user->resolver.ip;
WARN_LOG(SCENET, "AdhocServer: Invalid Opcode 0x%02X in Waiting State from %u.%u.%u.%u", user->rx[0], ip[0], ip[1], ip[2], ip[3]);
WARN_LOG(SCENET, "AdhocServer: Invalid Opcode 0x%02X in Waiting State from %s", user->rx[0], inet_ntoa(*(in_addr*)&user->resolver.ip));
// Logout User
logout_user(user);
@ -2026,8 +2017,7 @@ int server_loop(int server)
else
{
// Notify User
uint8_t * ip = (uint8_t *)&user->resolver.ip;
WARN_LOG(SCENET, "AdhocServer: Invalid Opcode 0x%02X in Logged-In State from %s (MAC: %02X:%02X:%02X:%02X:%02X:%02X - IP: %u.%u.%u.%u)", user->rx[0], (char *)user->resolver.name.data, user->resolver.mac.data[0], user->resolver.mac.data[1], user->resolver.mac.data[2], user->resolver.mac.data[3], user->resolver.mac.data[4], user->resolver.mac.data[5], ip[0], ip[1], ip[2], ip[3]);
WARN_LOG(SCENET, "AdhocServer: Invalid Opcode 0x%02X in Logged-In State from %s (MAC: %02x:%02x:%02x:%02x:%02x:%02x - IP: %s)", user->rx[0], (char *)user->resolver.name.data, user->resolver.mac.data[0], user->resolver.mac.data[1], user->resolver.mac.data[2], user->resolver.mac.data[3], user->resolver.mac.data[4], user->resolver.mac.data[5], inet_ntoa(*(in_addr*)&user->resolver.ip));
// Logout User
logout_user(user);

View file

@ -46,7 +46,7 @@
#define SERVER_STATUS_XMLOUT "www/status.xml"
// Server Shutdown Message
#define SERVER_SHUTDOWN_MESSAGE "PROMETHEUS HUB IS SHUTTING DOWN!"
#define SERVER_SHUTDOWN_MESSAGE "ADHOC SERVER HUB IS SHUTTING DOWN!"
typedef struct db_crosslink{
char id_from[PRODUCT_CODE_LENGTH + 1]; //SceNetAdhocctlProductCode id_from;
@ -298,7 +298,7 @@ void logout_user(SceNetAdhocctlUserNode * user);
/**
* Free Database Memory
*/
void free_database(void);
void free_database();
/**
* Connect User to Game Group
@ -358,7 +358,7 @@ void game_product_override(SceNetAdhocctlProductCode * product);
/**
* Update Status Logfile
*/
void update_status(void);
void update_status();
/**
* Server Entry Point

View file

@ -45,8 +45,8 @@
#include "Core/Instance.h"
static bool netInited;
static bool netInetInited;
static bool netApctlInited;
bool netInetInited;
bool netApctlInited;
u32 netDropRate = 0;
u32 netDropDuration = 0;
u32 netPoolAddr = 0;
@ -118,12 +118,25 @@ void __NetInit() {
net::Init();
InitLocalIP();
INFO_LOG(SCENET, "LocalHost IP will be %s", inet_ntoa(((sockaddr_in*)&localIP)->sin_addr));
char tmpmac[18];
SceNetEtherAddr mac;
getLocalMac(&mac);
INFO_LOG(SCENET, "LocalHost IP will be %s [MAC: %s]", inet_ntoa(((sockaddr_in*)&localIP)->sin_addr), mac2str(&mac, tmpmac));
//net::Init();
__ResetInitNetLib();
}
void __NetShutdown() {
// Checks to avoid confusing logspam
if (netAdhocctlInited) sceNetAdhocctlTerm();
if (netAdhocInited) sceNetAdhocTerm();
if (netApctlInited) sceNetApctlTerm();
if (netInetInited) sceNetInetTerm();
if (netInited) sceNetTerm();
__ResetInitNetLib();
net::Shutdown();
@ -149,6 +162,10 @@ void __NetDoState(PointerWrap &p) {
if (!s)
return;
auto cur_netInited = netInited;
auto cur_netInetInited = netInetInited;
auto cur_netApctlInited = netApctlInited;
p.Do(netInited);
p.Do(netInetInited);
p.Do(netApctlInited);
@ -170,6 +187,12 @@ void __NetDoState(PointerWrap &p) {
p.Do(netThread1Addr);
p.Do(netThread2Addr);
}
// Let's not change "Inited" value when Loading SaveState in the middle of multiplayer to prevent memory & port leaks
if (p.mode == p.MODE_READ) {
netApctlInited = cur_netApctlInited;
netInetInited = cur_netInetInited;
netInited = cur_netInited;
}
}
static inline u32 AllocUser(u32 size, bool fromTop, const char *name) {
@ -186,10 +209,32 @@ static inline void FreeUser(u32 &addr) {
}
static u32 sceNetTerm() {
//May also need to Terminate netAdhocctl and netAdhoc since the game (ie. GTA:VCS, Wipeout Pulse, etc) might not called them before calling sceNetTerm and causing them to behave strangely on the next sceNetInit+sceNetAdhocInit
// May also need to Terminate netAdhocctl and netAdhoc to free some resources & threads, since the game (ie. GTA:VCS, Wipeout Pulse, etc) might not called them before calling sceNetTerm and causing them to behave strangely on the next sceNetInit & sceNetAdhocInit
if (netAdhocctlInited) sceNetAdhocctlTerm();
if (netAdhocInited) sceNetAdhocTerm();
if (netApctlInited) sceNetApctlTerm();
if (netInetInited) sceNetInetTerm();
// Library is initialized
if (netInited) {
// Delete PDP Sockets
deleteAllPDP();
// Delete PTP Sockets
deleteAllPTP();
// Delete GameMode Buffer
//deleteAllGMB();
// Terminate Internet Library
//sceNetInetTerm();
// Unload Internet Modules (Just keep it in memory... unloading crashes?!)
// if (_manage_modules != 0) sceUtilityUnloadModule(PSP_MODULE_NET_INET);
// Library shutdown
}
WARN_LOG(SCENET, "sceNetTerm()");
netInited = false;
FreeUser(netPoolAddr);
@ -199,12 +244,20 @@ static u32 sceNetTerm() {
return 0;
}
// TODO: should that struct actually be initialized here?
static int sceNetInit(u32 poolSize, u32 calloutPri, u32 calloutStack, u32 netinitPri, u32 netinitStack) {
/*
Parameters:
poolsize - Memory pool size (appears to be for the whole of the networking library).
calloutprio - Priority of the SceNetCallout thread.
calloutstack - Stack size of the SceNetCallout thread (defaults to 4096 on non 1.5 firmware regardless of what value is passed).
netintrprio - Priority of the SceNetNetintr thread.
netintrstack - Stack size of the SceNetNetintr thread (defaults to 4096 on non 1.5 firmware regardless of what value is passed).
*/
static u32 sceNetInit(u32 poolSize, u32 calloutPri, u32 calloutStack, u32 netinitPri, u32 netinitStack) {
// TODO: Create Network Threads using given priority & stack
// TODO: The correct behavior is actually to allocate more and leak the other threads/pool.
// But we reset here for historic reasons (GTA:VCS potentially triggers this.)
if (netInited)
sceNetTerm();
sceNetTerm(); // This cleanup attempt might not worked when SaveState were loaded in the middle of multiplayer game and re-entering multiplayer, thus causing memory leaks & wasting binded ports. May be we shouldn't save/load "Inited" vars on SaveState?
if (poolSize == 0) {
return hleLogError(SCENET, SCE_KERNEL_ERROR_ILLEGAL_MEMSIZE, "invalid pool size");
@ -236,13 +289,32 @@ static int sceNetInit(u32 poolSize, u32 calloutPri, u32 calloutStack, u32 netini
WARN_LOG(SCENET, "sceNetInit(poolsize=%d, calloutpri=%i, calloutstack=%d, netintrpri=%i, netintrstack=%d) at %08x", poolSize, calloutPri, calloutStack, netinitPri, netinitStack, currentMIPS->pc);
netInited = true;
netMallocStat.maximum = poolSize;
netMallocStat.free = poolSize;
netMallocStat.pool = 0;
netMallocStat.pool = poolSize; // This should be the poolSize isn't?
netMallocStat.maximum = poolSize/2; // According to JPCSP's sceNetGetMallocStat this is Currently Used size = (poolSize - free), faked to half the pool
netMallocStat.free = poolSize - netMallocStat.maximum;
// Clear Socket Translator Memory
memset(&pdp, 0, sizeof(pdp));
memset(&ptp, 0, sizeof(ptp));
return hleLogSuccessI(SCENET, 0);
}
// Free(delete) thread info / data.
// Normal usage: sceKernelDeleteThread followed by sceNetFreeThreadInfo with the same threadID as argument
static int sceNetFreeThreadinfo(SceUID thid) {
ERROR_LOG(SCENET, "UNIMPL sceNetFreeThreadinfo(%i)", thid);
return 0;
}
// Abort a thread.
static int sceNetThreadAbort(SceUID thid) {
ERROR_LOG(SCENET, "UNIMPL sceNetThreadAbort(%i)", thid);
return 0;
}
static u32 sceWlanGetEtherAddr(u32 addrAddr) {
if (!Memory::IsValidRange(addrAddr, 6)) {
// More correctly, it should crash.
@ -364,7 +436,7 @@ static int sceNetInetInit() {
return 0;
}
static int sceNetInetTerm() {
int sceNetInetTerm() {
ERROR_LOG(SCENET, "UNIMPL sceNetInetTerm()");
netInetInited = false;
@ -380,7 +452,7 @@ static int sceNetApctlInit() {
return 0;
}
static int sceNetApctlTerm() {
int sceNetApctlTerm() {
ERROR_LOG(SCENET, "UNIMPL sceNeApctlTerm()");
netApctlInited = false;
@ -602,9 +674,9 @@ const HLEFunction sceNet[] = {
{0X89360950, &WrapI_UU<sceNetEtherNtostr>, "sceNetEtherNtostr", 'i', "xx" },
{0XD27961C9, &WrapI_UU<sceNetEtherStrton>, "sceNetEtherStrton", 'i', "xx" },
{0X0BF0A3AE, &WrapU_U<sceNetGetLocalEtherAddr>, "sceNetGetLocalEtherAddr", 'x', "x" },
{0X50647530, nullptr, "sceNetFreeThreadinfo", '?', "" },
{0X50647530, &WrapI_I<sceNetFreeThreadinfo>, "sceNetFreeThreadinfo", 'i', "i" },
{0XCC393E48, &WrapI_U<sceNetGetMallocStat>, "sceNetGetMallocStat", 'i', "x" },
{0XAD6844C6, nullptr, "sceNetThreadAbort", '?', "" },
{0XAD6844C6, &WrapI_I<sceNetThreadAbort>, "sceNetThreadAbort", 'i', "i" },
};
const HLEFunction sceNetResolver[] = {

View file

@ -60,7 +60,7 @@ typedef struct SceNetInetSockaddr {
uint8_t sa_len;
uint8_t sa_family;
uint8_t sa_data[14];
} SceNetInetSockaddr;
} PACK SceNetInetSockaddr;
// Sockaddr_in
typedef struct SceNetInetSockaddrIn {
@ -69,19 +69,19 @@ typedef struct SceNetInetSockaddrIn {
u16_le sin_port; //uint16_t
u32_le sin_addr; //uint32_t
uint8_t sin_zero[8];
} SceNetInetSockaddrIn;
} PACK SceNetInetSockaddrIn;
// Polling Event Field
typedef struct SceNetInetPollfd { //similar format to pollfd in 32bit (pollfd in 64bit have different size)
s32_le fd;
s16_le events;
s16_le revents;
} SceNetInetPollfd;
} PACK SceNetInetPollfd;
struct ProductStruct {
typedef struct ProductStruct { // Similar to SceNetAdhocctlAdhocId ?
s32_le unknown; // Unknown, set to 0 // Product Type ?
char product[PRODUCT_CODE_LENGTH]; // Game ID (Example: ULUS10000)
};
} PACK ProductStruct;
struct ApctlHandler {
u32 entryPoint;
@ -90,6 +90,9 @@ struct ApctlHandler {
class PointerWrap;
extern bool netInetInited;
extern bool netApctlInited;
void Register_sceNet();
void Register_sceWlanDrv();
void Register_sceNetUpnp();
@ -100,4 +103,7 @@ void __NetInit();
void __NetShutdown();
void __NetDoState(PointerWrap &p);
int sceNetInetPoll(void *fds, u32 nfds, int timeout);
int sceNetInetPoll(void *fds, u32 nfds, int timeout);
int sceNetInetTerm();
int sceNetApctlTerm();
static u32 sceNetTerm();

File diff suppressed because it is too large Load diff

View file

@ -17,6 +17,8 @@
#pragma once
#include "Core/HLE/proAdhoc.h"
typedef struct MatchingArgs {
u32_le data[6]; //ContextID, Opcode, bufAddr[ to MAC], OptLen, OptAddr[, EntryPoint]
} PACK;
@ -25,6 +27,7 @@ class PointerWrap;
void Register_sceNetAdhoc();
u32_le __CreateHLELoop(u32_le* loopAddr, const char* sceFuncName, const char* hleFuncName, const char* tagName = NULL);
void __NetAdhocInit();
void __NetAdhocShutdown();
void __NetAdhocDoState(PointerWrap &p);
@ -37,5 +40,12 @@ int sceNetAdhocctlCreate(const char * groupName);
// May need to use these from sceNet.cpp
extern bool netAdhocInited;
extern bool netAdhocctlInited;
extern int adhocDefaultTimeout;
extern int adhocEventPollDelayMS;
extern int adhocMatchingEventDelayMS;
extern int adhocEventDelayMS;
extern std::recursive_mutex adhocEvtMtx;
extern int IsAdhocctlInCB;
int sceNetAdhocctlTerm();
int sceNetAdhocTerm();