2014-07-31 18:55:42 +00:00
// Copyright (c) 2013- PPSSPP Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0 or later versions.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
// proAdhoc
// This is a direct port of Coldbird's code from http://code.google.com/p/aemu/
// All credit goes to him!
2013-11-28 11:38:45 +00:00
2019-11-09 23:23:19 +00:00
# if !defined(_WIN32)
# include <unistd.h>
2020-01-04 00:41:54 +00:00
# include <netinet/tcp.h>
2020-02-25 09:29:06 +00:00
# include <sys/ioctl.h>
# include <sys/socket.h>
# include <sys/types.h>
# include <ifaddrs.h>
2019-11-09 23:23:19 +00:00
# endif
2014-03-15 18:56:52 +00:00
# include <cstring>
2013-11-28 11:38:45 +00:00
# include "util/text/parsers.h"
2019-12-23 17:04:03 +00:00
# include "thread/threadutil.h"
2020-08-10 07:12:51 +00:00
# include "Common/Serialize/SerializeFuncs.h"
2014-07-31 18:55:42 +00:00
# include "Core/Core.h"
2016-05-28 05:00:14 +00:00
# include "Core/Host.h"
2014-07-31 18:55:42 +00:00
# include "Core/HLE/sceKernelInterrupt.h"
# include "Core/HLE/sceKernelThread.h"
# include "Core/HLE/sceKernelMemory.h"
2020-07-20 09:38:39 +00:00
# include "Core/Instance.h"
2013-11-10 01:26:31 +00:00
# include "proAdhoc.h"
2015-01-11 03:55:25 +00:00
# include "i18n/i18n.h"
2013-11-10 01:26:31 +00:00
2020-01-17 19:32:09 +00:00
uint16_t portOffset ;
uint32_t minSocketTimeoutUS ;
2013-11-10 01:26:31 +00:00
uint32_t fakePoolSize = 0 ;
SceNetAdhocMatchingContext * contexts = NULL ;
int one = 1 ;
bool friendFinderRunning = false ;
SceNetAdhocctlPeerInfo * friends = NULL ;
SceNetAdhocctlScanInfo * networks = NULL ;
2014-07-31 18:55:42 +00:00
SceNetAdhocctlScanInfo * newnetworks = NULL ;
2013-11-10 01:26:31 +00:00
int threadStatus = ADHOCCTL_STATE_DISCONNECTED ;
2019-12-23 17:04:03 +00:00
int actionAfterAdhocMipsCall ;
2014-07-31 18:55:42 +00:00
int actionAfterMatchingMipsCall ;
// Broadcast MAC
uint8_t broadcastMAC [ ETHER_ADDR_LEN ] = { 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF } ;
2020-02-25 09:29:06 +00:00
int metasocket = ( int ) INVALID_SOCKET ;
2013-11-10 01:26:31 +00:00
SceNetAdhocctlParameter parameter ;
2014-07-31 18:55:42 +00:00
SceNetAdhocctlAdhocId product_code ;
2013-11-10 01:26:31 +00:00
std : : thread friendFinderThread ;
2017-03-18 21:33:43 +00:00
std : : recursive_mutex peerlock ;
2013-11-10 01:26:31 +00:00
SceNetAdhocPdpStat * pdp [ 255 ] ;
SceNetAdhocPtpStat * ptp [ 255 ] ;
2016-10-21 10:35:54 +00:00
std : : vector < std : : string > chatLog ;
std : : string name = " " ;
std : : string incoming = " " ;
std : : string message = " " ;
2016-10-31 14:22:57 +00:00
bool chatScreenVisible = false ;
bool updateChatScreen = false ;
int newChat = 0 ;
2020-03-19 08:21:00 +00:00
bool isOriPort = false ;
2019-11-09 23:23:19 +00:00
bool isLocalServer = false ;
2020-02-25 09:29:06 +00:00
sockaddr LocalhostIP ;
sockaddr LocalIP ;
2020-03-19 06:46:02 +00:00
int defaultWlanChannel = PSP_SYSTEMPARAM_ADHOC_CHANNEL_1 ; // Don't put 0(Auto) here, it needed to be a valid/actual channel number
2019-11-09 23:23:19 +00:00
2019-12-23 17:04:03 +00:00
bool isLocalMAC ( const SceNetEtherAddr * addr ) {
2014-07-31 18:55:42 +00:00
SceNetEtherAddr saddr ;
getLocalMac ( & saddr ) ;
2013-11-10 01:26:31 +00:00
2020-03-19 08:21:00 +00:00
return ( memcmp ( ( const void * ) addr , ( const void * ) & saddr , ETHER_ADDR_LEN ) = = 0 ) ;
2013-11-10 01:26:31 +00:00
}
2019-12-23 17:04:03 +00:00
bool isPDPPortInUse ( uint16_t port ) {
2014-07-31 18:55:42 +00:00
// Iterate Elements
2019-12-23 17:04:03 +00:00
for ( int i = 0 ; i < 255 ; i + + ) if ( pdp [ i ] ! = NULL & & pdp [ i ] - > lport = = port ) return true ;
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
// Unused Port
2019-12-23 17:04:03 +00:00
return false ;
2013-11-10 01:26:31 +00:00
}
2019-12-23 17:04:03 +00:00
bool isPTPPortInUse ( uint16_t port ) {
2013-11-10 01:26:31 +00:00
// Iterate Sockets
2019-12-23 17:04:03 +00:00
for ( int i = 0 ; i < 255 ; i + + ) if ( ptp [ i ] ! = NULL & & ptp [ i ] - > lport = = port ) return true ;
2013-11-10 01:26:31 +00:00
// Unused Port
2019-12-23 17:04:03 +00:00
return false ;
}
2020-07-23 00:41:41 +00:00
std : : string mac2str ( SceNetEtherAddr * mac ) {
char str [ 18 ] = " ::::: " ;
2019-12-23 17:04:03 +00:00
2020-07-23 00:41:41 +00:00
if ( mac ! = NULL ) {
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 ] ) ;
}
2019-12-23 17:04:03 +00:00
2020-07-23 00:41:41 +00:00
return std : : string ( str ) ;
2013-11-10 01:26:31 +00:00
}
2014-07-31 18:55:42 +00:00
SceNetAdhocMatchingMemberInternal * addMember ( SceNetAdhocMatchingContext * context , SceNetEtherAddr * mac ) {
2014-06-24 16:43:03 +00:00
if ( context = = NULL | | mac = = NULL ) return NULL ;
2014-07-31 18:55:42 +00:00
SceNetAdhocMatchingMemberInternal * peer = findPeer ( context , mac ) ;
2019-12-23 17:04:03 +00:00
// Already existed
if ( peer ! = NULL ) {
2020-07-23 00:41:41 +00:00
WARN_LOG ( SCENET , " Member Peer Already Existed! Updating [%s] " , mac2str ( mac ) . c_str ( ) ) ;
2019-12-23 17:04:03 +00:00
peer - > lastping = CoreTiming : : GetGlobalTimeUsScaled ( ) ;
}
2014-06-24 16:43:03 +00:00
// Member is not added yet
2019-12-23 17:04:03 +00:00
else {
2014-06-24 16:43:03 +00:00
peer = ( SceNetAdhocMatchingMemberInternal * ) malloc ( sizeof ( SceNetAdhocMatchingMemberInternal ) ) ;
if ( peer ! = NULL ) {
memset ( peer , 0 , sizeof ( SceNetAdhocMatchingMemberInternal ) ) ;
peer - > mac = * mac ;
2019-12-23 17:04:03 +00:00
peer - > lastping = CoreTiming : : GetGlobalTimeUsScaled ( ) ;
2014-06-24 16:43:03 +00:00
peer - > next = context - > peerlist ;
context - > peerlist = peer ;
}
}
2014-07-31 18:55:42 +00:00
return peer ;
2014-06-24 16:43:03 +00:00
}
2014-07-31 18:55:42 +00:00
void addFriend ( SceNetAdhocctlConnectPacketS2C * packet ) {
if ( packet = = NULL ) return ;
// Multithreading Lock
2017-03-18 21:33:43 +00:00
std : : lock_guard < std : : recursive_mutex > guard ( peerlock ) ;
2014-07-31 18:55:42 +00:00
SceNetAdhocctlPeerInfo * peer = findFriend ( & packet - > mac ) ;
// Already existed
if ( peer ! = NULL ) {
2019-12-27 19:37:27 +00:00
u32 tmpip = packet - > ip ;
2020-07-23 00:41:41 +00:00
WARN_LOG ( SCENET , " Friend Peer Already Existed! Updating [%s][%s][%s] " , mac2str ( & packet - > mac ) . c_str ( ) , inet_ntoa ( * ( struct in_addr * ) & tmpip ) , packet - > name . data ) ; //inet_ntoa(*(in_addr*)&packet->ip)
2014-07-31 18:55:42 +00:00
peer - > nickname = packet - > name ;
peer - > mac_addr = packet - > mac ;
peer - > ip_addr = packet - > ip ;
// Update TimeStamp
peer - > last_recv = CoreTiming : : GetGlobalTimeUsScaled ( ) ;
}
2019-12-23 17:04:03 +00:00
else {
2014-07-31 18:55:42 +00:00
// Allocate Structure
peer = ( SceNetAdhocctlPeerInfo * ) malloc ( sizeof ( SceNetAdhocctlPeerInfo ) ) ;
// Allocated Structure
if ( peer ! = NULL ) {
// Clear Memory
memset ( peer , 0 , sizeof ( SceNetAdhocctlPeerInfo ) ) ;
2014-06-24 16:43:03 +00:00
2014-07-31 18:55:42 +00:00
// Save Nickname
peer - > nickname = packet - > name ;
2014-06-24 16:43:03 +00:00
2014-07-31 18:55:42 +00:00
// Save MAC Address
peer - > mac_addr = packet - > mac ;
2014-06-24 16:43:03 +00:00
2014-07-31 18:55:42 +00:00
// Save IP Address
peer - > ip_addr = packet - > ip ;
2014-06-24 16:43:03 +00:00
2014-07-31 18:55:42 +00:00
// TimeStamp
peer - > last_recv = CoreTiming : : GetGlobalTimeUsScaled ( ) ;
2014-06-24 16:43:03 +00:00
2014-07-31 18:55:42 +00:00
// Link to existing Peers
peer - > next = friends ;
2014-06-24 16:43:03 +00:00
2014-07-31 18:55:42 +00:00
// Link into Peerlist
friends = peer ;
2014-06-24 16:43:03 +00:00
}
}
}
2014-07-31 18:55:42 +00:00
SceNetAdhocctlPeerInfo * findFriend ( SceNetEtherAddr * MAC ) {
if ( MAC = = NULL ) return NULL ;
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
// Friends Reference
SceNetAdhocctlPeerInfo * peer = friends ;
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
// Iterate Friends
for ( ; peer ! = NULL ; peer = peer - > next ) {
if ( IsMatch ( peer - > mac_addr , * MAC ) ) break ;
}
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
// Return found friend
return peer ;
2013-11-10 01:26:31 +00:00
}
void changeBlockingMode ( int fd , int nonblocking ) {
2014-07-31 18:55:42 +00:00
unsigned long on = 1 ;
unsigned long off = 0 ;
2020-01-17 19:32:09 +00:00
# if defined(_WIN32)
if ( nonblocking ) {
2014-07-31 18:55:42 +00:00
// Change to Non-Blocking Mode
ioctlsocket ( fd , FIONBIO , & on ) ;
}
else {
// Change to Blocking Mode
ioctlsocket ( fd , FIONBIO , & off ) ;
}
2020-01-17 19:32:09 +00:00
// If they have O_NONBLOCK, use the POSIX way to do it. On POSIX sockets Error code would be EINPROGRESS instead of EAGAIN
//#elif defined(O_NONBLOCK)
2013-11-10 01:26:31 +00:00
# else
2020-01-17 19:32:09 +00:00
int flags = fcntl ( fd , F_GETFL , 0 ) ;
// Fixme: O_NONBLOCK is defined but broken on SunOS 4.1.x and AIX 3.2.5.
if ( flags = = - 1 )
flags = 0 ;
if ( nonblocking ) {
// Set Non-Blocking Flag
fcntl ( fd , F_SETFL , flags | O_NONBLOCK ) ;
}
2014-07-31 18:55:42 +00:00
else {
// Remove Non-Blocking Flag
fcntl ( fd , F_SETFL , flags & ~ O_NONBLOCK ) ;
}
2020-01-17 19:32:09 +00:00
// Otherwise, use the old way of doing it (UNIX way). On UNIX sockets Error code would be EAGAIN instead of EINPROGRESS
/*#else
if ( nonblocking ) {
// Change to Non - Blocking Mode
ioctl ( fd , FIONBIO , ( char * ) & on ) ;
}
else {
// Change to Blocking Mode
ioctl ( fd , FIONBIO , ( char * ) & off ) ;
} */
2013-11-10 01:26:31 +00:00
# endif
}
2019-12-23 17:04:03 +00:00
int countAvailableNetworks ( ) {
2014-07-31 18:55:42 +00:00
// Network Count
int count = 0 ;
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
// Group Reference
SceNetAdhocctlScanInfo * group = networks ;
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
// Count Groups
for ( ; group ! = NULL ; group = group - > next ) count + + ;
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
// Return Network Count
return count ;
2013-11-10 01:26:31 +00:00
}
2014-06-24 16:43:03 +00:00
SceNetAdhocctlScanInfo * findGroup ( SceNetEtherAddr * MAC ) {
if ( MAC = = NULL ) return NULL ;
2014-07-31 18:55:42 +00:00
// Groups Reference
2014-06-24 16:43:03 +00:00
SceNetAdhocctlScanInfo * group = networks ;
2014-07-31 18:55:42 +00:00
// Iterate Groups
2014-06-24 16:43:03 +00:00
for ( ; group ! = NULL ; group = group - > next ) {
if ( IsMatch ( group - > bssid . mac_addr , * MAC ) ) break ;
}
2014-07-31 18:55:42 +00:00
// Return found group
2014-06-24 16:43:03 +00:00
return group ;
}
2020-07-12 21:11:36 +00:00
void freeGroupsRecursive ( SceNetAdhocctlScanInfo * node ) {
2014-06-24 16:43:03 +00:00
// End of List
if ( node = = NULL ) return ;
// Increase Recursion Depth
freeGroupsRecursive ( node - > next ) ;
// Free Memory
free ( node ) ;
2019-12-23 17:04:03 +00:00
node = NULL ;
2014-06-24 16:43:03 +00:00
}
2019-12-23 17:04:03 +00:00
void deleteAllPDP ( ) {
2014-07-31 18:55:42 +00:00
// Iterate Element
2019-12-23 17:04:03 +00:00
for ( int i = 0 ; i < 255 ; i + + ) {
2014-07-31 18:55:42 +00:00
// Active Socket
if ( pdp [ i ] ! = NULL ) {
// Close Socket
closesocket ( pdp [ i ] - > id ) ;
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
// Free Memory
free ( pdp [ i ] ) ;
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
// Delete Reference
pdp [ i ] = NULL ;
}
}
2013-11-10 01:26:31 +00:00
}
2019-12-23 17:04:03 +00:00
void deleteAllPTP ( ) {
2014-07-31 18:55:42 +00:00
// Iterate Element
2019-12-23 17:04:03 +00:00
for ( int i = 0 ; i < 255 ; i + + ) {
2014-07-31 18:55:42 +00:00
// Active Socket
if ( ptp [ i ] ! = NULL ) {
// Close Socket
closesocket ( ptp [ i ] - > id ) ;
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
// Free Memory
free ( ptp [ i ] ) ;
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
// Delete Reference
ptp [ i ] = NULL ;
}
}
2013-11-10 01:26:31 +00:00
}
void deleteFriendByIP ( uint32_t ip ) {
2014-07-31 18:55:42 +00:00
// Previous Peer Reference
SceNetAdhocctlPeerInfo * prev = NULL ;
// Peer Pointer
SceNetAdhocctlPeerInfo * peer = friends ;
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
// Iterate Peers
for ( ; peer ! = NULL ; peer = peer - > next ) {
// Found Peer
if ( peer - > ip_addr = = ip ) {
2019-12-23 17:04:03 +00:00
2014-07-31 18:55:42 +00:00
// Multithreading Lock
2015-09-13 13:07:13 +00:00
peerlock . lock ( ) ;
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
// Unlink Left (Beginning)
2019-12-23 17:04:03 +00:00
/*if (prev == NULL) friends = peer->next;
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
// Unlink Left (Other)
else prev - > next = peer - > next ;
2019-12-23 17:04:03 +00:00
*/
2013-11-10 01:26:31 +00:00
2019-12-27 19:37:27 +00:00
u32 tmpip = peer - > ip_addr ;
2020-07-23 00:41:41 +00:00
INFO_LOG ( SCENET , " Removing Friend Peer %s [%s] " , mac2str ( & peer - > mac_addr ) . c_str ( ) , inet_ntoa ( * ( struct in_addr * ) & tmpip ) ) ; //inet_ntoa(*(in_addr*)&peer->ip_addr)
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
// Free Memory
2019-12-23 17:04:03 +00:00
//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 ( ) ;
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
// Stop Search
break ;
}
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
// Set Previous Reference
prev = peer ;
}
2013-11-10 01:26:31 +00:00
}
2019-12-23 17:04:03 +00:00
int findFreeMatchingID ( ) {
2014-07-31 18:55:42 +00:00
// Minimum Matching ID
int min = 1 ;
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
// Maximum Matching ID
int max = 0 ;
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
// Find highest Matching ID
2019-12-23 17:04:03 +00:00
SceNetAdhocMatchingContext * item = contexts ;
for ( ; item ! = NULL ; item = item - > next ) {
2014-07-31 18:55:42 +00:00
// New Maximum
if ( max < item - > id ) max = item - > id ;
}
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
// Find unoccupied ID
2019-12-23 17:04:03 +00:00
int i = min ;
for ( ; i < max ; i + + ) {
2014-07-31 18:55:42 +00:00
// Found unoccupied ID
if ( findMatchingContext ( i ) = = NULL ) return i ;
}
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
// Append at virtual end
return max + 1 ;
2013-11-10 01:26:31 +00:00
}
SceNetAdhocMatchingContext * findMatchingContext ( int id ) {
2014-07-31 18:55:42 +00:00
// Iterate Matching Context List
2019-12-23 17:04:03 +00:00
SceNetAdhocMatchingContext * item = contexts ;
for ( ; item ! = NULL ; item = item - > next ) { // Found Matching ID
2014-07-31 18:55:42 +00:00
if ( item - > id = = id ) return item ;
}
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
// Context not found
return NULL ;
2013-11-10 01:26:31 +00:00
}
2014-07-31 18:55:42 +00:00
/**
* Find Outgoing Request Target Peer
* @ param context Matching Context Pointer
* @ return Internal Peer Reference or . . . NULL
*/
SceNetAdhocMatchingMemberInternal * findOutgoingRequest ( SceNetAdhocMatchingContext * context )
{
// Iterate Peer List for Matching Target
2019-12-23 17:04:03 +00:00
SceNetAdhocMatchingMemberInternal * peer = context - > peerlist ;
for ( ; peer ! = NULL ; peer = peer - > next )
2014-07-31 18:55:42 +00:00
{
// Found Peer in List
if ( peer - > state = = PSP_ADHOC_MATCHING_PEER_OUTGOING_REQUEST ) return peer ;
}
// Peer not found
return NULL ;
}
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
/**
* Remove unneeded Peer Data after being accepted to a match
* @ param context Matching Context Pointer
*/
void postAcceptCleanPeerList ( SceNetAdhocMatchingContext * context )
{
2019-12-23 17:04:03 +00:00
int delcount = 0 ;
int peercount = 0 ;
2014-07-31 18:55:42 +00:00
// Acquire Peer Lock
peerlock . lock ( ) ;
// Iterate Peer List
SceNetAdhocMatchingMemberInternal * peer = context - > peerlist ;
while ( peer ! = NULL )
{
// Save next Peer just in case we have to delete this one
SceNetAdhocMatchingMemberInternal * next = peer - > next ;
// Unneeded Peer
2019-12-23 17:04:03 +00:00
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 + + ;
}
2014-07-31 18:55:42 +00:00
// Move to Next Peer
peer = next ;
2019-12-23 17:04:03 +00:00
peercount + + ;
2014-07-31 18:55:42 +00:00
}
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
// Free Peer Lock
peerlock . unlock ( ) ;
2019-12-23 17:04:03 +00:00
INFO_LOG ( SCENET , " Removing Unneeded Peer (%i/%i) " , delcount , peercount ) ;
2013-11-10 01:26:31 +00:00
}
2014-07-31 18:55:42 +00:00
/**
* Add Sibling - Data that was sent with Accept - Datagram
* @ param context Matching Context Pointer
* @ param siblingcount Number of Siblings
* @ param siblings Sibling MAC Array
*/
void postAcceptAddSiblings ( SceNetAdhocMatchingContext * context , int siblingcount , SceNetEtherAddr * siblings )
{
// Cast Sibling MAC Array to uint8_t
// PSP CPU has a problem with non-4-byte aligned Pointer Access.
// As the buffer of "siblings" isn't properly aligned I don't want to risk a crash.
uint8_t * siblings_u8 = ( uint8_t * ) siblings ;
// Iterate Siblings
2019-12-23 17:04:03 +00:00
for ( int i = 0 ; i < siblingcount ; i + + )
2014-07-31 18:55:42 +00:00
{
// Allocate Memory
SceNetAdhocMatchingMemberInternal * sibling = ( SceNetAdhocMatchingMemberInternal * ) malloc ( sizeof ( SceNetAdhocMatchingMemberInternal ) ) ;
// Allocated Memory
if ( sibling ! = NULL )
{
// Clear Memory
memset ( sibling , 0 , sizeof ( SceNetAdhocMatchingMemberInternal ) ) ;
// Save MAC Address
memcpy ( & sibling - > mac , siblings_u8 + sizeof ( SceNetEtherAddr ) * i , sizeof ( SceNetEtherAddr ) ) ;
// Set Peer State
sibling - > state = PSP_ADHOC_MATCHING_PEER_CHILD ;
// Initialize Ping Timer
sibling - > lastping = CoreTiming : : GetGlobalTimeUsScaled ( ) ; //real_time_now()*1000000.0;
2020-07-24 03:13:27 +00:00
peerlock . lock ( ) ;
2014-07-31 18:55:42 +00:00
// Link Peer, should check whether it's already added before
sibling - > next = context - > peerlist ;
context - > peerlist = sibling ;
2020-07-24 03:13:27 +00:00
peerlock . unlock ( ) ;
2014-07-31 18:55:42 +00:00
2020-07-25 04:46:47 +00:00
// Spawn Established Event. FIXME: ESTABLISHED event should only be triggered for Parent/P2P peer?
//spawnLocalEvent(context, PSP_ADHOC_MATCHING_EVENT_ESTABLISHED, &sibling->mac, 0, NULL);
2014-07-31 18:55:42 +00:00
2020-07-23 00:41:41 +00:00
INFO_LOG ( SCENET , " Accepting Peer %s " , mac2str ( & sibling - > mac ) . c_str ( ) ) ;
2014-07-31 18:55:42 +00:00
}
}
}
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
/**
* Count Children Peers ( for Parent )
* @ param context Matching Context Pointer
* @ return Number of Children
*/
2019-12-23 17:04:03 +00:00
s32_le countChildren ( SceNetAdhocMatchingContext * context , const bool excludeTimedout )
2014-07-31 18:55:42 +00:00
{
// Children Counter
s32_le count = 0 ;
// Iterate Peer List for Matching Target
2019-12-23 17:04:03 +00:00
SceNetAdhocMatchingMemberInternal * peer = context - > peerlist ;
for ( ; peer ! = NULL ; peer = peer - > next )
2014-07-31 18:55:42 +00:00
{
2019-12-23 17:04:03 +00:00
// Exclude timedout members?
if ( ! excludeTimedout | | peer - > lastping ! = 0 )
2014-07-31 18:55:42 +00:00
// Increase Children Counter
if ( peer - > state = = PSP_ADHOC_MATCHING_PEER_CHILD ) count + + ;
}
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
// Return Children Count
return count ;
}
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
/**
* Find Peer in Context by MAC
* @ param context Matching Context Pointer
* @ param mac Peer MAC Address
* @ return Internal Peer Reference or . . . NULL
*/
SceNetAdhocMatchingMemberInternal * findPeer ( SceNetAdhocMatchingContext * context , SceNetEtherAddr * mac )
{
// Iterate Peer List for Matching Target
2019-12-23 17:04:03 +00:00
SceNetAdhocMatchingMemberInternal * peer = context - > peerlist ;
for ( ; peer ! = NULL ; peer = peer - > next )
2014-07-31 18:55:42 +00:00
{
// Found Peer in List
if ( memcmp ( & peer - > mac , mac , sizeof ( SceNetEtherAddr ) ) = = 0 )
{
// Return Peer Pointer
return peer ;
}
}
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
// Peer not found
return NULL ;
}
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
/**
* Find Parent Peer
* @ param context Matching Context Pointer
* @ return Internal Peer Reference or . . . NULL
*/
SceNetAdhocMatchingMemberInternal * findParent ( SceNetAdhocMatchingContext * context )
{
// Iterate Peer List for Matching Target
2019-12-23 17:04:03 +00:00
SceNetAdhocMatchingMemberInternal * peer = context - > peerlist ;
for ( ; peer ! = NULL ; peer = peer - > next )
2014-07-31 18:55:42 +00:00
{
// Found Peer in List
if ( peer - > state = = PSP_ADHOC_MATCHING_PEER_PARENT ) return peer ;
}
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
// Peer not found
return NULL ;
}
/**
* Find P2P Buddy Peer
* @ param context Matching Context Pointer
* @ return Internal Peer Reference or . . . NULL
*/
2019-12-23 17:04:03 +00:00
SceNetAdhocMatchingMemberInternal * findP2P ( SceNetAdhocMatchingContext * context , const bool excludeTimedout )
2014-07-31 18:55:42 +00:00
{
// Iterate Peer List for Matching Target
SceNetAdhocMatchingMemberInternal * peer = context - > peerlist ;
for ( ; peer ! = NULL ; peer = peer - > next )
{
2019-12-23 17:04:03 +00:00
// Exclude timedout members?
if ( ! excludeTimedout | | peer - > lastping ! = 0 )
2014-07-31 18:55:42 +00:00
// Found Peer in List
if ( peer - > state = = PSP_ADHOC_MATCHING_PEER_P2P ) return peer ;
}
// Peer not found
return NULL ;
}
/**
* Delete Peer from List
* @ param context Matching Context Pointer
* @ param peer Internal Peer Reference
*/
2020-03-10 12:14:17 +00:00
void deletePeer ( SceNetAdhocMatchingContext * context , SceNetAdhocMatchingMemberInternal * & peer )
2014-07-31 18:55:42 +00:00
{
// Valid Arguments
if ( context ! = NULL & & peer ! = NULL )
{
peerlock . lock ( ) ;
// Previous Peer Reference
SceNetAdhocMatchingMemberInternal * previous = NULL ;
// Iterate Peer List
SceNetAdhocMatchingMemberInternal * item = context - > peerlist ;
for ( ; item ! = NULL ; item = item - > next )
{
// Found Peer Match
if ( item = = peer ) break ;
// Set Previous Peer
previous = item ;
}
if ( item ! = NULL ) {
// Middle Item
if ( previous ! = NULL ) previous - > next = item - > next ;
// Beginning Item
else context - > peerlist = item - > next ;
2020-07-23 00:41:41 +00:00
INFO_LOG ( SCENET , " Removing Member Peer %s " , mac2str ( & peer - > mac ) . c_str ( ) ) ;
2014-07-31 18:55:42 +00:00
}
// Free Peer Memory
free ( peer ) ;
peer = NULL ;
peerlock . unlock ( ) ;
}
}
/**
* Safely Link Thread Message to Event Thread Stack
* @ param context Matching Context Pointer
* @ param message Thread Message Pointer
*/
void linkEVMessage ( SceNetAdhocMatchingContext * context , ThreadMessage * message )
{
// Lock Access
context - > eventlock - > lock ( ) ;
// Link Message
message - > next = context - > event_stack ;
context - > event_stack = message ;
// Unlock Access
context - > eventlock - > unlock ( ) ;
}
/**
* Safely Link Thread Message to IO Thread Stack
* @ param context Matching Context Pointer
* @ param message Thread Message Pointer
*/
void linkIOMessage ( SceNetAdhocMatchingContext * context , ThreadMessage * message )
{
// Lock Access
context - > inputlock - > lock ( ) ;
// Link Message
message - > next = context - > input_stack ;
context - > input_stack = message ;
// Unlock Access
context - > inputlock - > unlock ( ) ;
}
/**
* Send Generic Thread Message
* @ param context Matching Context Pointer
* @ param stack ADHOC_MATCHING_EVENT_STACK or ADHOC_MATCHING_INPUT_STACK
* @ param mac Target MAC
* @ param opcode Message Opcode
* @ param optlen Optional Data Length
* @ param opt Optional Data
*/
void sendGenericMessage ( SceNetAdhocMatchingContext * context , int stack , SceNetEtherAddr * mac , int opcode , int optlen , const void * opt )
{
// Calculate Required Memory Size
uint32_t size = sizeof ( ThreadMessage ) + optlen ;
// Allocate Memory
uint8_t * memory = ( uint8_t * ) malloc ( size ) ;
// Allocated Memory
if ( memory ! = NULL )
{
// Clear Memory
memset ( memory , 0 , size ) ;
// Cast Header
ThreadMessage * header = ( ThreadMessage * ) memory ;
// Set Message Opcode
header - > opcode = opcode ;
// Set Peer MAC Address
header - > mac = * mac ;
// Set Optional Data Length
header - > optlen = optlen ;
// Set Optional Data
memcpy ( memory + sizeof ( ThreadMessage ) , opt , optlen ) ;
// Link Thread Message
if ( stack = = PSP_ADHOC_MATCHING_EVENT_STACK ) linkEVMessage ( context , header ) ;
// Link Thread Message to Input Stack
else linkIOMessage ( context , header ) ;
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
// Exit Function
return ;
}
peerlock . lock ( ) ;
// Out of Memory Emergency Delete
2020-03-10 12:14:17 +00:00
auto peer = findPeer ( context , mac ) ;
deletePeer ( context , peer ) ;
2014-07-31 18:55:42 +00:00
peerlock . unlock ( ) ;
}
/**
* Send Accept Message from P2P - > P2P or Parent - > Children
* @ param context Matching Context Pointer
* @ param peer Target Peer
* @ param optlen Optional Data Length
* @ param opt Optional Data
*/
void sendAcceptMessage ( SceNetAdhocMatchingContext * context , SceNetAdhocMatchingMemberInternal * peer , int optlen , const void * opt )
{
// Send Accept Message
sendGenericMessage ( context , PSP_ADHOC_MATCHING_INPUT_STACK , & peer - > mac , PSP_ADHOC_MATCHING_PACKET_ACCEPT , optlen , opt ) ;
}
/**
* Send Join Request from P2P - > P2P or Children - > Parent
* @ param context Matching Context Pointer
* @ param peer Target Peer
* @ param optlen Optional Data Length
* @ param opt Optional Data
*/
void sendJoinRequest ( SceNetAdhocMatchingContext * context , SceNetAdhocMatchingMemberInternal * peer , int optlen , const void * opt )
{
// Send Join Message
sendGenericMessage ( context , PSP_ADHOC_MATCHING_INPUT_STACK , & peer - > mac , PSP_ADHOC_MATCHING_PACKET_JOIN , optlen , opt ) ;
}
/**
* Send Cancel Message to Peer ( has various effects )
* @ param context Matching Context Pointer
* @ param peer Target Peer
* @ param optlen Optional Data Length
* @ param opt Optional Data
*/
void sendCancelMessage ( SceNetAdhocMatchingContext * context , SceNetAdhocMatchingMemberInternal * peer , int optlen , const void * opt )
{
// Send Cancel Message
sendGenericMessage ( context , PSP_ADHOC_MATCHING_INPUT_STACK , & peer - > mac , PSP_ADHOC_MATCHING_PACKET_CANCEL , optlen , opt ) ;
}
/**
* Send Bulk Data to Peer
* @ param context Matching Context Pointer
* @ param peer Target Peer
* @ param datalen Data Length
* @ param data Data
*/
void sendBulkData ( SceNetAdhocMatchingContext * context , SceNetAdhocMatchingMemberInternal * peer , int datalen , const void * data )
{
// Send Bulk Data Message
sendGenericMessage ( context , PSP_ADHOC_MATCHING_INPUT_STACK , & peer - > mac , PSP_ADHOC_MATCHING_PACKET_BULK , datalen , data ) ;
}
/**
* Abort Bulk Data Transfer ( if in progress )
* @ param context Matching Context Pointer
* @ param peer Target Peer
*/
void abortBulkTransfer ( SceNetAdhocMatchingContext * context , SceNetAdhocMatchingMemberInternal * peer )
{
// Send Bulk Data Abort Message
sendGenericMessage ( context , PSP_ADHOC_MATCHING_INPUT_STACK , & peer - > mac , PSP_ADHOC_MATCHING_PACKET_BULK_ABORT , 0 , NULL ) ;
}
/**
* Notify all established Peers about new Kid in the Neighborhood
* @ param context Matching Context Pointer
* @ param peer New Kid
*/
void sendBirthMessage ( SceNetAdhocMatchingContext * context , SceNetAdhocMatchingMemberInternal * peer )
{
// Send Birth Message
sendGenericMessage ( context , PSP_ADHOC_MATCHING_INPUT_STACK , & peer - > mac , PSP_ADHOC_MATCHING_PACKET_BIRTH , 0 , NULL ) ;
}
/**
* Notify all established Peers about abandoned Child
* @ param context Matching Context Pointer
* @ param peer Abandoned Child
*/
void sendDeathMessage ( SceNetAdhocMatchingContext * context , SceNetAdhocMatchingMemberInternal * peer )
{
// Send Death Message
sendGenericMessage ( context , PSP_ADHOC_MATCHING_INPUT_STACK , & peer - > mac , PSP_ADHOC_MATCHING_PACKET_DEATH , 0 , NULL ) ;
}
/**
* Return Number of Connected Peers
* @ param context Matching Context Pointer
* @ return Number of Connected Peers
*/
2019-12-23 17:04:03 +00:00
uint32_t countConnectedPeers ( SceNetAdhocMatchingContext * context , const bool excludeTimedout )
2014-07-31 18:55:42 +00:00
{
// Peer Count
uint32_t count = 0 ;
// Parent Mode
if ( context - > mode = = PSP_ADHOC_MATCHING_MODE_PARENT )
{
// Number of Children + 1 Parent (Self)
2019-12-23 17:04:03 +00:00
count = countChildren ( context , excludeTimedout ) + 1 ;
2014-07-31 18:55:42 +00:00
}
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
// Child Mode
else if ( context - > mode = = PSP_ADHOC_MATCHING_MODE_CHILD )
{
// Default to 1 Child (Self)
count = 1 ;
// Connected to Parent
if ( findParent ( context ) ! = NULL )
{
2020-03-19 06:46:02 +00:00
// Add Number of Siblings + 1 Parent
count + = countChildren ( context , excludeTimedout ) + 1 ; // Since count is already started from 1, Do we need to +1 here? Ys vs. Sora no Kiseki seems to show wrong number of players without +1 here
2014-07-31 18:55:42 +00:00
}
}
// P2P Mode
else
{
// Default to 1 P2P Client (Self)
count = 1 ;
// Connected to another P2P Client
2019-12-23 17:04:03 +00:00
if ( findP2P ( context , excludeTimedout ) ! = NULL )
2014-07-31 18:55:42 +00:00
{
// Add P2P Brother
count + + ;
}
}
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
// Return Peer Count
return count ;
}
/**
* Spawn Local Event for Event Thread
* @ param context Matching Context Pointer
* @ param event Event ID
* @ param mac Event Source MAC
* @ param optlen Optional Data Length
* @ param opt Optional Data
*/
void spawnLocalEvent ( SceNetAdhocMatchingContext * context , int event , SceNetEtherAddr * mac , int optlen , void * opt )
{
// Spawn Local Event
sendGenericMessage ( context , PSP_ADHOC_MATCHING_EVENT_STACK , mac , event , optlen , opt ) ;
}
/**
* Handle Timeouts in Matching Context
2019-12-23 17:04:03 +00:00
* @ param context Matching Context Pointer
2014-07-31 18:55:42 +00:00
*/
void handleTimeout ( SceNetAdhocMatchingContext * context )
{
peerlock . lock ( ) ;
// Iterate Peer List
2019-12-23 17:04:03 +00:00
SceNetAdhocMatchingMemberInternal * peer = context - > peerlist ;
while ( peer ! = NULL & & contexts ! = NULL & & coreState ! = CORE_POWERDOWN )
2014-07-31 18:55:42 +00:00
{
// Get Next Pointer (to avoid crash on memory freeing)
SceNetAdhocMatchingMemberInternal * next = peer - > next ;
u64_le now = CoreTiming : : GetGlobalTimeUsScaled ( ) ; //real_time_now()*1000000.0
2019-12-23 17:04:03 +00:00
// Timeout!, may be we shouldn't kick timedout members ourself and let the game do it
2014-07-31 18:55:42 +00:00
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 ) | |
2019-12-23 17:04:03 +00:00
( 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?
}
2014-07-31 18:55:42 +00:00
2020-07-23 00:41:41 +00:00
INFO_LOG ( SCENET , " TimedOut Member Peer %s (%lldms) " , mac2str ( & peer - > mac ) . c_str ( ) , ( context - > timeout / 1000 ) ) ;
2014-07-31 18:55:42 +00:00
// Delete Peer from List
deletePeer ( context , peer ) ;
2019-12-23 17:04:03 +00:00
//peer->lastping = 0; //Let's just make the game kick timedout members during sceNetAdhocMatchingGetMembers
2014-07-31 18:55:42 +00:00
}
// Move Pointer
peer = next ;
}
peerlock . unlock ( ) ;
}
/**
* Recursive Stack Cleaner
* @ param node Current Thread Message Node
*/
2020-03-10 12:14:17 +00:00
void clearStackRecursive ( ThreadMessage * & node )
2014-07-31 18:55:42 +00:00
{
// Not End of List
if ( node ! = NULL ) clearStackRecursive ( node - > next ) ;
// Free Last Existing Node of List (NULL is handled in _free)
free ( node ) ;
2019-12-23 17:04:03 +00:00
node = NULL ;
2014-07-31 18:55:42 +00:00
}
/**
* Clear Thread Stack
* @ param context Matching Context Pointer
* @ param stack ADHOC_MATCHING_EVENT_STACK or ADHOC_MATCHING_INPUT_STACK
*/
void clearStack ( SceNetAdhocMatchingContext * context , int stack )
{
if ( context = = NULL ) return ;
// Clear Event Stack
if ( stack = = PSP_ADHOC_MATCHING_EVENT_STACK )
{
context - > eventlock - > lock ( ) ;
// Free Memory Recursively
clearStackRecursive ( context - > event_stack ) ;
// Destroy Reference
context - > event_stack = NULL ;
context - > eventlock - > unlock ( ) ;
}
// Clear IO Stack
else
{
context - > inputlock - > lock ( ) ;
// Free Memory Recursively
clearStackRecursive ( context - > input_stack ) ;
// Destroy Reference
context - > input_stack = NULL ;
context - > inputlock - > unlock ( ) ;
}
}
/**
* Clear Peer List
* @ param context Matching Context Pointer
*/
void clearPeerList ( SceNetAdhocMatchingContext * context )
{
// Acquire Peer Lock
peerlock . lock ( ) ;
// Iterate Peer List
SceNetAdhocMatchingMemberInternal * peer = context - > peerlist ;
while ( peer ! = NULL )
{
// Grab Next Pointer
context - > peerlist = peer - > next ; //SceNetAdhocMatchingMemberInternal * next = peer->next;
// Delete Peer
free ( peer ) ; //deletePeer(context, peer);
2019-12-23 17:04:03 +00:00
// 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();
2014-07-31 18:55:42 +00:00
// Move Pointer
peer = context - > peerlist ; //peer = next;
}
// Free Peer Lock
peerlock . unlock ( ) ;
}
2020-08-10 04:20:42 +00:00
void AfterMatchingMipsCall : : DoState ( PointerWrap & p ) {
auto s = p . Section ( " AfterMatchingMipsCall " , 1 , 4 ) ;
if ( ! s )
return ;
if ( s > = 1 ) {
Do ( p , EventID ) ;
} else {
EventID = - 1 ;
}
if ( s > = 4 ) {
Do ( p , contextID ) ;
Do ( p , bufAddr ) ;
} else {
contextID = - 1 ;
bufAddr = 0 ;
}
}
2019-12-23 17:04:03 +00:00
// 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)
2014-07-31 18:55:42 +00:00
void AfterMatchingMipsCall : : run ( MipsCall & call ) {
2019-12-23 17:04:03 +00:00
if ( context = = NULL ) {
peerlock . lock ( ) ;
context = findMatchingContext ( contextID ) ;
peerlock . unlock ( ) ;
2014-07-31 18:55:42 +00:00
}
2019-12-23 17:04:03 +00:00
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 ) ;
2020-05-04 14:44:40 +00:00
//SetMatchingInCallback(context, false);
2020-07-25 04:38:08 +00:00
DEBUG_LOG ( SCENET , " AfterMatchingMipsCall::run [ID=%i][Event=%d][%s] [cbId: %u][retV0: %08x] " , contextID , EventID , mac2str ( ( SceNetEtherAddr * ) Memory : : GetPointer ( bufAddr ) ) . c_str ( ) , call . cbId , v0 ) ;
if ( Memory : : IsValidAddress ( bufAddr ) ) userMemory . Free ( bufAddr ) ;
2019-12-23 17:04:03 +00:00
//call.setReturnValue(v0);
2014-07-31 18:55:42 +00:00
}
2019-12-23 17:04:03 +00:00
void AfterMatchingMipsCall : : SetData ( int ContextID , int eventId , u32_le BufAddr ) {
contextID = ContextID ;
2014-07-31 18:55:42 +00:00
EventID = eventId ;
2019-11-13 05:56:29 +00:00
bufAddr = BufAddr ;
2014-07-31 18:55:42 +00:00
peerlock . lock ( ) ;
context = findMatchingContext ( ContextID ) ;
peerlock . unlock ( ) ;
}
2019-12-23 17:04:03 +00:00
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 ;
}
2020-08-10 04:20:42 +00:00
void AfterAdhocMipsCall : : DoState ( PointerWrap & p ) {
auto s = p . Section ( " AfterAdhocMipsCall " , 1 , 4 ) ;
if ( ! s )
return ;
if ( s > = 3 ) {
Do ( p , HandlerID ) ;
Do ( p , EventID ) ;
Do ( p , argsAddr ) ;
} else {
HandlerID = - 1 ;
EventID = - 1 ;
argsAddr = 0 ;
}
}
2019-12-23 17:04:03 +00:00
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 ;
}
2014-07-31 18:55:42 +00:00
// Make sure MIPS calls have been fully executed before the next notifyAdhocctlHandlers
2015-01-04 13:07:44 +00:00
void notifyAdhocctlHandlers ( u32 flag , u32 error ) {
__UpdateAdhocctlHandlers ( flag , error ) ;
2014-07-31 18:55:42 +00:00
}
// 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
2019-12-23 17:04:03 +00:00
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
2019-11-13 05:56:29 +00:00
MatchingArgs argsNew ;
2019-12-23 17:04:03 +00:00
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 ) ;
2019-11-13 05:56:29 +00:00
argsNew . data [ 0 ] = context - > id ;
argsNew . data [ 1 ] = msg - > opcode ;
2019-12-23 17:04:03 +00:00
argsNew . data [ 2 ] = dataBufAddr ;
2019-11-13 05:56:29 +00:00
argsNew . data [ 3 ] = msg - > optlen ;
2019-12-23 17:04:03 +00:00
argsNew . data [ 4 ] = dataBufAddr + 8 ; // OptData Addr
2019-11-13 05:56:29 +00:00
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
2014-07-31 18:55:42 +00:00
// ScheduleEvent_Threadsafe_Immediate seems to get mixed up with interrupt (returning from mipscall inside an interrupt) and getting invalid address before returning from interrupt
2019-11-13 05:56:29 +00:00
__UpdateMatchingHandler ( argsNew ) ;
2014-07-31 18:55:42 +00:00
}
2020-07-12 21:11:36 +00:00
void freeFriendsRecursive ( SceNetAdhocctlPeerInfo * node , int32_t * count ) {
2014-07-31 18:55:42 +00:00
// End of List
if ( node = = NULL ) return ;
// Increase Recursion Depth
2019-12-23 17:04:03 +00:00
freeFriendsRecursive ( node - > next , count ) ;
2014-07-31 18:55:42 +00:00
// Free Memory
free ( node ) ;
2019-12-23 17:04:03 +00:00
node = NULL ;
if ( count ! = NULL ) ( * count ) + + ;
}
2020-07-12 21:11:36 +00:00
void timeoutFriendsRecursive ( SceNetAdhocctlPeerInfo * node , int32_t * count ) {
2019-12-23 17:04:03 +00:00
// 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 ) + + ;
2014-07-31 18:55:42 +00:00
}
2013-11-10 01:26:31 +00:00
2016-10-21 10:35:54 +00:00
void sendChat ( std : : string chatString ) {
SceNetAdhocctlChatPacketC2S chat ;
2020-03-02 17:23:12 +00:00
auto n = GetI18NCategory ( " Networking " ) ;
2016-10-21 10:35:54 +00:00
chat . base . opcode = OPCODE_CHAT ;
2016-10-22 16:06:07 +00:00
//TODO check network inited, check send success or not, chatlog.pushback error on failed send, pushback error on not connected
2016-10-25 10:35:52 +00:00
if ( friendFinderRunning )
{
2016-10-22 16:06:07 +00:00
// Send Chat to Server
2016-10-23 17:49:12 +00:00
if ( ! chatString . empty ( ) ) {
2020-03-08 13:32:32 +00:00
//maximum char allowed is 64 character for compability with original server (pro.coldbird.net)
message = chatString . substr ( 0 , 60 ) ; // 64 return chat variable corrupted is it out of memory?
strcpy ( chat . message , message . c_str ( ) ) ;
//Send Chat Messages
int chatResult = send ( metasocket , ( const char * ) & chat , sizeof ( chat ) , 0 ) ;
NOTICE_LOG ( SCENET , " Send Chat %s to Adhoc Server " , chat . message ) ;
name = g_Config . sNickName . c_str ( ) ;
chatLog . push_back ( name . substr ( 0 , 8 ) + " : " + chat . message ) ;
2016-10-31 14:22:57 +00:00
if ( chatScreenVisible ) {
updateChatScreen = true ;
2016-10-23 17:49:12 +00:00
}
}
2016-10-26 21:21:07 +00:00
}
else {
2016-10-27 22:46:31 +00:00
chatLog . push_back ( n - > T ( " You're in Offline Mode, go to lobby or online hall " ) ) ;
2016-10-31 14:22:57 +00:00
if ( chatScreenVisible ) {
updateChatScreen = true ;
2016-10-25 10:35:52 +00:00
}
}
2016-10-21 10:35:54 +00:00
}
std : : vector < std : : string > getChatLog ( ) {
// this log used by chat screen
2016-10-22 16:06:07 +00:00
if ( chatLog . size ( ) > 50 ) {
//erase the first 40 element limit the chatlog size
chatLog . erase ( chatLog . begin ( ) , chatLog . begin ( ) + 40 ) ;
}
2016-10-21 10:35:54 +00:00
return chatLog ;
}
2014-07-31 18:55:42 +00:00
int friendFinder ( ) {
2019-12-23 17:04:03 +00:00
setCurrentThreadName ( " FriendFinder " ) ;
2014-07-31 18:55:42 +00:00
// Receive Buffer
int rxpos = 0 ;
uint8_t rx [ 1024 ] ;
// Chat Packet
SceNetAdhocctlChatPacketC2S chat ;
chat . base . opcode = OPCODE_CHAT ;
// Last Ping Time
uint64_t lastping = 0 ;
// Last Time Reception got updated
uint64_t lastreceptionupdate = 0 ;
uint64_t now ;
// Log Startup
INFO_LOG ( SCENET , " FriendFinder: Begin of Friend Finder Thread " ) ;
// Finder Loop
while ( friendFinderRunning ) {
// Acquire Network Lock
//_acquireNetworkLock();
2020-07-12 01:04:55 +00:00
// Reconnect when disconnected while Adhocctl is still inited
if ( metasocket = = ( int ) INVALID_SOCKET & & netAdhocctlInited ) {
if ( g_Config . bEnableWlan & & initNetwork ( & product_code ) = = 0 ) {
networkInited = true ;
}
2014-07-31 18:55:42 +00:00
}
2013-11-10 01:26:31 +00:00
2020-07-12 01:04:55 +00:00
if ( networkInited ) {
// Ping Server
now = real_time_now ( ) * 1000000.0 ; // Use real_time_now()*1000000.0 instead of CoreTiming::GetGlobalTimeUsScaled() if the game gets disconnected from AdhocServer too soon when FPS wasn't stable
if ( now - lastping > = PSP_ADHOCCTL_PING_TIMEOUT ) { // We may 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
lastping = now ;
// Prepare Packet
uint8_t opcode = OPCODE_PING ;
// Send Ping to Server, may failed with socket error 10054/10053 if someone else with the same IP already connected to AdHoc Server (the server might need to be modified to differentiate MAC instead of IP)
int iResult = send ( metasocket , ( const char * ) & opcode , 1 , 0 ) ;
if ( iResult = = SOCKET_ERROR ) {
ERROR_LOG ( SCENET , " FriendFinder: Socket Error (%i) when sending OPCODE_PING " , errno ) ;
networkInited = false ;
shutdown ( metasocket , SD_BOTH ) ;
closesocket ( metasocket ) ;
metasocket = ( int ) INVALID_SOCKET ;
}
}
2013-11-10 01:26:31 +00:00
2020-07-12 01:04:55 +00:00
// Wait for Incoming Data
int received = recv ( metasocket , ( char * ) ( rx + rxpos ) , sizeof ( rx ) - rxpos , 0 ) ;
2013-11-10 01:26:31 +00:00
2020-07-12 01:04:55 +00:00
// Free Network Lock
//_freeNetworkLock();
2013-11-10 01:26:31 +00:00
2020-07-12 01:04:55 +00:00
// Received Data
if ( received > 0 ) {
// Fix Position
rxpos + = received ;
2013-11-10 01:26:31 +00:00
2020-07-12 01:04:55 +00:00
// Log Incoming Traffic
//printf("Received %d Bytes of Data from Server\n", received);
INFO_LOG ( SCENET , " Received %d Bytes of Data from Adhoc Server " , received ) ;
2014-07-31 18:55:42 +00:00
}
2020-07-12 01:04:55 +00:00
// Handle Packets
if ( rxpos > 0 ) {
// BSSID Packet
if ( rx [ 0 ] = = OPCODE_CONNECT_BSSID ) {
// Enough Data available
if ( rxpos > = ( int ) sizeof ( SceNetAdhocctlConnectBSSIDPacketS2C ) ) {
// Cast Packet
SceNetAdhocctlConnectBSSIDPacketS2C * packet = ( SceNetAdhocctlConnectBSSIDPacketS2C * ) rx ;
2020-07-23 00:41:41 +00:00
INFO_LOG ( SCENET , " FriendFinder: Incoming OPCODE_CONNECT_BSSID [%s] " , mac2str ( & packet - > mac ) . c_str ( ) ) ;
2020-07-12 01:04:55 +00:00
// 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 ) ;
2016-10-24 07:29:17 +00:00
}
2020-07-12 01:04:55 +00:00
else {
setState ( ADHOCCTL_STATE_CONNECTED ) ;
notifyAdhocctlHandlers ( ADHOCCTL_EVENT_CONNECT , 0 ) ;
} */
// Update User BSSID
parameter . bssid . mac_addr = packet - > mac ; // This packet seems to contains Adhoc Group Creator's BSSID (similar to AP's BSSID) so it shouldn't get mixed up with local MAC address
// Notify Event Handlers
//notifyAdhocctlHandlers(ADHOCCTL_EVENT_CONNECT, 0);
// Change State
threadStatus = ADHOCCTL_STATE_CONNECTED ;
// Give time a little time
//sceKernelDelayThread(adhocEventDelayMS * 1000);
//sleep_ms(adhocEventDelayMS);
// Move RX Buffer
memmove ( rx , rx + sizeof ( SceNetAdhocctlConnectBSSIDPacketS2C ) , sizeof ( rx ) - sizeof ( SceNetAdhocctlConnectBSSIDPacketS2C ) ) ;
// Fix RX Buffer Length
rxpos - = sizeof ( SceNetAdhocctlConnectBSSIDPacketS2C ) ;
2016-10-24 07:29:17 +00:00
}
2020-07-12 01:04:55 +00:00
}
2019-12-23 17:04:03 +00:00
2020-07-12 01:04:55 +00:00
// Chat Packet
else if ( rx [ 0 ] = = 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 = " " ;
name = ( char * ) packet - > name . data ;
incoming . append ( name . substr ( 0 , 8 ) ) ;
incoming . append ( " : " ) ;
incoming . append ( ( char * ) packet - > base . message ) ;
chatLog . push_back ( incoming ) ;
//im new to pointer btw :( doesn't know its safe or not this should update the chat screen when data coming
if ( chatScreenVisible ) {
updateChatScreen = true ;
}
else {
if ( newChat < 50 ) {
newChat + = 1 ;
}
}
2014-07-31 18:55:42 +00:00
2020-07-12 01:04:55 +00:00
// Move RX Buffer
memmove ( rx , rx + sizeof ( SceNetAdhocctlChatPacketS2C ) , sizeof ( rx ) - sizeof ( SceNetAdhocctlChatPacketS2C ) ) ;
2014-07-31 18:55:42 +00:00
2020-07-12 01:04:55 +00:00
// Fix RX Buffer Length
rxpos - = sizeof ( SceNetAdhocctlChatPacketS2C ) ;
2016-10-21 10:35:54 +00:00
}
2020-07-12 01:04:55 +00:00
}
// Connect Packet
else if ( rx [ 0 ] = = OPCODE_CONNECT ) {
// Enough Data available
if ( rxpos > = ( int ) sizeof ( SceNetAdhocctlConnectPacketS2C ) ) {
// Cast Packet
SceNetAdhocctlConnectPacketS2C * packet = ( SceNetAdhocctlConnectPacketS2C * ) rx ;
// Fix strings with null-terminated
packet - > name . data [ ADHOCCTL_NICKNAME_LEN - 1 ] = 0 ;
// Log Incoming Peer
u32_le ipaddr = packet - > ip ;
2020-07-23 00:41:41 +00:00
INFO_LOG ( SCENET , " FriendFinder: Incoming OPCODE_CONNECT [%s][%s][%s] " , mac2str ( & packet - > mac ) . c_str ( ) , inet_ntoa ( * ( in_addr * ) & ipaddr ) , packet - > name . data ) ;
2020-07-12 01:04:55 +00:00
// 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 " ) ;
//do we need ip?
//joined.append((char *)packet->ip);
chatLog . push_back ( incoming ) ;
//im new to pointer btw :( doesn't know its safe or not this should update the chat screen when data coming
if ( chatScreenVisible ) {
updateChatScreen = true ;
}
2014-07-31 18:55:42 +00:00
# ifdef LOCALHOST_AS_PEER
2020-07-12 01:04:55 +00:00
setUserCount ( getActivePeerCount ( ) ) ;
2014-07-31 18:55:42 +00:00
# else
2020-07-12 01:04:55 +00:00
// setUserCount(getActivePeerCount()+1);
2014-07-31 18:55:42 +00:00
# endif
2014-06-24 16:43:03 +00:00
2014-07-31 18:55:42 +00:00
// Move RX Buffer
2020-07-12 01:04:55 +00:00
memmove ( rx , rx + sizeof ( SceNetAdhocctlConnectPacketS2C ) , sizeof ( rx ) - sizeof ( SceNetAdhocctlConnectPacketS2C ) ) ;
2014-06-24 16:43:03 +00:00
2020-07-12 01:04:55 +00:00
// Fix RX Buffer Length
rxpos - = sizeof ( SceNetAdhocctlConnectPacketS2C ) ;
}
2014-07-31 18:55:42 +00:00
}
2014-06-24 16:43:03 +00:00
2020-07-12 01:04:55 +00:00
// Disconnect Packet
else if ( rx [ 0 ] = = OPCODE_DISCONNECT ) {
// Enough Data available
if ( rxpos > = ( int ) sizeof ( SceNetAdhocctlDisconnectPacketS2C ) ) {
// Cast Packet
SceNetAdhocctlDisconnectPacketS2C * packet = ( SceNetAdhocctlDisconnectPacketS2C * ) rx ;
2014-06-24 16:43:03 +00:00
2020-07-12 01:04:55 +00:00
DEBUG_LOG ( SCENET , " FriendFinder: OPCODE_DISCONNECT " ) ;
2019-12-23 17:04:03 +00:00
2020-07-12 01:04:55 +00:00
// Log Incoming Peer Delete Request
INFO_LOG ( SCENET , " FriendFinder: Incoming Peer Data Delete Request... " ) ;
2019-12-23 17:04:03 +00:00
2020-07-12 01:04:55 +00:00
// Delete User by IP, should delete by MAC since IP can be shared (behind NAT) isn't?
deleteFriendByIP ( packet - > ip ) ;
2013-11-10 01:26:31 +00:00
2020-07-12 01:04:55 +00:00
// Update HUD User Count
2014-07-31 18:55:42 +00:00
# ifdef LOCALHOST_AS_PEER
2020-07-12 01:04:55 +00:00
setUserCount ( _getActivePeerCount ( ) ) ;
2014-07-31 18:55:42 +00:00
# else
//setUserCount(_getActivePeerCount()+1);
# endif
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
// Move RX Buffer
2020-07-12 01:04:55 +00:00
memmove ( rx , rx + sizeof ( SceNetAdhocctlDisconnectPacketS2C ) , sizeof ( rx ) - sizeof ( SceNetAdhocctlDisconnectPacketS2C ) ) ;
2014-07-31 18:55:42 +00:00
2020-07-12 01:04:55 +00:00
// Fix RX Buffer Length
rxpos - = sizeof ( SceNetAdhocctlDisconnectPacketS2C ) ;
}
2014-07-31 18:55:42 +00:00
}
2020-07-12 01:04:55 +00:00
// Scan Packet
else if ( rx [ 0 ] = = OPCODE_SCAN ) {
// Enough Data available
if ( rxpos > = ( int ) sizeof ( SceNetAdhocctlScanPacketS2C ) ) {
// Cast Packet
SceNetAdhocctlScanPacketS2C * packet = ( SceNetAdhocctlScanPacketS2C * ) rx ;
2014-07-31 18:55:42 +00:00
2020-07-12 01:04:55 +00:00
DEBUG_LOG ( SCENET , " FriendFinder: OPCODE_SCAN " ) ;
2019-12-23 17:04:03 +00:00
2020-07-12 01:04:55 +00:00
// Log Incoming Network Information
INFO_LOG ( SCENET , " Incoming Group Information... " ) ;
2019-12-23 17:04:03 +00:00
2020-07-12 01:04:55 +00:00
// Multithreading Lock
peerlock . lock ( ) ;
// Allocate Structure Data
SceNetAdhocctlScanInfo * group = ( SceNetAdhocctlScanInfo * ) malloc ( sizeof ( SceNetAdhocctlScanInfo ) ) ;
// Allocated Structure Data
if ( group ! = NULL ) {
// Clear Memory, should this be done only when allocating new group?
memset ( group , 0 , sizeof ( SceNetAdhocctlScanInfo ) ) ;
2014-07-31 18:55:42 +00:00
2020-07-12 01:04:55 +00:00
// Link to existing Groups
group - > next = newnetworks ;
2014-07-31 18:55:42 +00:00
2020-07-12 01:04:55 +00:00
// Copy Group Name
group - > group_name = packet - > group ;
2020-03-10 12:14:17 +00:00
2020-07-12 01:04:55 +00:00
// Set Group Host
group - > bssid . mac_addr = packet - > mac ;
2020-03-10 12:14:17 +00:00
2020-07-12 01:04:55 +00:00
// Set group parameters
// Since 0 is not a valid active channel we fake the channel for Automatic Channel (JPCSP use 11 as default). Ridge Racer 2 will ignore any groups with channel 0 or that doesn't matched with channel value returned from sceUtilityGetSystemParamInt (which mean sceUtilityGetSystemParamInt must not return channel 0 when connected to a network?)
group - > channel = parameter . channel ; //(parameter.channel == PSP_SYSTEMPARAM_ADHOC_CHANNEL_AUTOMATIC) ? defaultWlanChannel : parameter.channel;
group - > mode = ADHOCCTL_MODE_ADHOC ; //adhocctlCurrentMode;
2014-07-31 18:55:42 +00:00
2020-07-12 01:04:55 +00:00
// Link into Group List
newnetworks = group ;
}
// Multithreading Unlock
peerlock . unlock ( ) ;
2014-07-31 18:55:42 +00:00
2020-07-12 01:04:55 +00:00
// Move RX Buffer
memmove ( rx , rx + sizeof ( SceNetAdhocctlScanPacketS2C ) , sizeof ( rx ) - sizeof ( SceNetAdhocctlScanPacketS2C ) ) ;
2014-07-31 18:55:42 +00:00
2020-07-12 01:04:55 +00:00
// Fix RX Buffer Length
rxpos - = sizeof ( SceNetAdhocctlScanPacketS2C ) ;
2014-07-31 18:55:42 +00:00
}
2020-07-12 01:04:55 +00:00
}
2014-07-31 18:55:42 +00:00
2020-07-12 01:04:55 +00:00
// Scan Complete Packet
else if ( rx [ 0 ] = = OPCODE_SCAN_COMPLETE ) {
DEBUG_LOG ( SCENET , " FriendFinder: OPCODE_SCAN_COMPLETE " ) ;
// Log Scan Completion
INFO_LOG ( SCENET , " FriendFinder: Incoming Scan complete response... " ) ;
// Reset current networks to prevent disbanded host to be listed again
peerlock . lock ( ) ;
if ( networks ! = newnetworks ) {
freeGroupsRecursive ( networks ) ;
networks = newnetworks ;
}
newnetworks = NULL ;
2014-07-31 18:55:42 +00:00
peerlock . unlock ( ) ;
2020-07-12 01:04:55 +00:00
// Notify Event Handlers
//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);
2014-07-31 18:55:42 +00:00
// Move RX Buffer
2020-07-12 01:04:55 +00:00
memmove ( rx , rx + 1 , sizeof ( rx ) - 1 ) ;
2014-07-31 18:55:42 +00:00
// Fix RX Buffer Length
2020-07-12 01:04:55 +00:00
rxpos - = 1 ;
2020-03-10 12:14:17 +00:00
}
2014-07-31 18:55:42 +00:00
}
}
2019-12-23 17:04:03 +00:00
// This delay time should be 100ms when there is an event otherwise 500ms ?
sleep_ms ( 1 ) ; // Using 1ms for faster response just like AdhocServer?
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
// Don't do anything if it's paused, otherwise the log will be flooded
2019-12-23 17:04:03 +00:00
while ( Core_IsStepping ( ) & & coreState ! = CORE_POWERDOWN & & friendFinderRunning ) sleep_ms ( 1 ) ;
2014-07-31 18:55:42 +00:00
}
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
// Groups/Networks should be deallocated isn't?
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
// Prevent the games from having trouble to reInitiate Adhoc (the next NetInit -> PdpCreate after NetTerm)
threadStatus = ADHOCCTL_STATE_DISCONNECTED ;
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
// Log Shutdown
INFO_LOG ( SCENET , " FriendFinder: End of Friend Finder Thread " ) ;
2014-06-24 16:43:03 +00:00
2014-07-31 18:55:42 +00:00
// Return Success
return 0 ;
2013-11-10 01:26:31 +00:00
}
2019-12-23 17:04:03 +00:00
int getActivePeerCount ( const bool excludeTimedout ) {
2014-07-31 18:55:42 +00:00
// Counter
int count = 0 ;
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
// #ifdef LOCALHOST_AS_PEER
// // Increase for Localhost
// count++;
// #endif
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
// Peer Reference
SceNetAdhocctlPeerInfo * peer = friends ;
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
// Iterate Peers
for ( ; peer ! = NULL ; peer = peer - > next ) {
2019-12-23 17:04:03 +00:00
// Increase Counter, Should we exclude peers pending for timed out?
if ( ! excludeTimedout | | peer - > last_recv ! = 0 )
count + + ;
2014-07-31 18:55:42 +00:00
}
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
// Return Result
return count ;
2013-11-10 01:26:31 +00:00
}
2020-02-25 09:29:06 +00:00
int getLocalIp ( sockaddr_in * SocketAddress ) {
if ( metasocket ! = ( int ) INVALID_SOCKET ) {
struct sockaddr_in localAddr ;
localAddr . sin_addr . s_addr = INADDR_ANY ;
socklen_t addrLen = sizeof ( localAddr ) ;
if ( SOCKET_ERROR ! = getsockname ( metasocket , ( struct sockaddr * ) & localAddr , & addrLen ) ) {
if ( isLocalServer ) {
localAddr . sin_addr = ( ( sockaddr_in * ) & LocalhostIP ) - > sin_addr ;
}
SocketAddress - > sin_addr = localAddr . sin_addr ;
return 0 ;
}
}
// Fallback if not connected to AdhocServer
2017-08-29 20:41:50 +00:00
# if defined(_WIN32)
2013-11-28 11:38:45 +00:00
// Get local host name
2019-11-09 23:23:19 +00:00
char szHostName [ 256 ] = " " ;
2013-11-28 11:38:45 +00:00
2020-02-25 09:29:06 +00:00
if ( : : gethostname ( szHostName , sizeof ( szHostName ) ) ) {
2013-11-28 11:38:45 +00:00
// Error handling
}
// Get local IP addresses
2020-02-25 09:29:06 +00:00
struct hostent * pHost = 0 ;
pHost = : : gethostbyname ( szHostName ) ; // On Non-Windows (UNIX/POSIX) gethostbyname("localhost") will always returns a useless 127.0.0.1, while on Windows it returns LAN IP when available
if ( pHost ) {
2013-11-28 11:38:45 +00:00
memcpy ( & SocketAddress - > sin_addr , pHost - > h_addr_list [ 0 ] , pHost - > h_length ) ;
2019-11-09 23:23:19 +00:00
if ( isLocalServer ) {
2020-02-25 09:29:06 +00:00
SocketAddress - > sin_addr = ( ( sockaddr_in * ) & LocalhostIP ) - > sin_addr ;
2019-11-09 23:23:19 +00:00
}
2013-11-28 11:38:45 +00:00
return 0 ;
}
return - 1 ;
2020-02-25 09:29:06 +00:00
# elif defined(getifaddrs) // On Android: Requires __ANDROID_API__ >= 24
struct ifaddrs * ifAddrStruct = NULL ;
struct ifaddrs * ifa = NULL ;
getifaddrs ( & ifAddrStruct ) ;
if ( ifAddrStruct ! = NULL ) {
for ( ifa = ifAddrStruct ; ifa ! = NULL ; ifa = ifa - > ifa_next ) {
if ( ! ifa - > ifa_addr ) {
continue ;
}
if ( ifa - > ifa_addr - > sa_family = = AF_INET ) { // check it is IP4
// is a valid IP4 Address
SocketAddress - > sin_addr = ( ( struct sockaddr_in * ) ifa - > ifa_addr ) - > sin_addr ;
break ;
}
}
freeifaddrs ( ifAddrStruct ) ;
2019-11-09 23:23:19 +00:00
if ( isLocalServer ) {
2020-02-25 09:29:06 +00:00
SocketAddress - > sin_addr = ( ( sockaddr_in * ) & LocalhostIP ) - > sin_addr ;
2019-11-09 23:23:19 +00:00
}
return 0 ;
}
2019-12-23 17:04:03 +00:00
return - 1 ;
2020-02-25 09:29:06 +00:00
# else // Alternative way
int sock = socket ( AF_INET , SOCK_DGRAM , 0 ) ;
if ( sock ! = SOCKET_ERROR ) {
const char * kGoogleDnsIp = " 8.8.8.8 " ; // Needs to be an IP string so it can be resolved as fast as possible to IP, doesn't need to be reachable
uint16_t kDnsPort = 53 ;
struct sockaddr_in serv ;
memset ( & serv , 0 , sizeof ( serv ) ) ;
serv . sin_family = AF_INET ;
serv . sin_addr . s_addr = inet_addr ( kGoogleDnsIp ) ;
serv . sin_port = htons ( kDnsPort ) ;
int err = connect ( sock , ( const sockaddr * ) & serv , sizeof ( serv ) ) ;
if ( err ! = SOCKET_ERROR ) {
sockaddr_in name ;
socklen_t namelen = sizeof ( name ) ;
err = getsockname ( sock , ( sockaddr * ) & name , & namelen ) ;
if ( err ! = SOCKET_ERROR ) {
SocketAddress - > sin_addr = name . sin_addr ; // May be we should cache this so it doesn't need to use connect all the time, or even better cache it when connecting to adhoc server to get an accurate IP
closesocket ( sock ) ;
if ( isLocalServer ) {
SocketAddress - > sin_addr = ( ( sockaddr_in * ) & LocalhostIP ) - > sin_addr ;
}
return 0 ;
}
}
closesocket ( sock ) ;
}
return - 1 ;
2013-11-10 01:26:31 +00:00
# endif
}
2014-06-24 16:43:03 +00:00
uint32_t getLocalIp ( int sock ) {
struct sockaddr_in localAddr ;
localAddr . sin_addr . s_addr = INADDR_ANY ;
socklen_t addrLen = sizeof ( localAddr ) ;
getsockname ( sock , ( struct sockaddr * ) & localAddr , & addrLen ) ;
2019-11-09 23:23:19 +00:00
if ( isLocalServer ) {
2020-02-25 09:29:06 +00:00
localAddr . sin_addr = ( ( sockaddr_in * ) & LocalhostIP ) - > sin_addr ;
2019-11-09 23:23:19 +00:00
}
2014-06-24 16:43:03 +00:00
return localAddr . sin_addr . s_addr ;
}
2020-03-19 08:21:00 +00:00
static std : : vector < std : : pair < uint32_t , uint32_t > > InitPrivateIPRanges ( ) {
struct sockaddr_in saNet , saMask ;
std : : vector < std : : pair < uint32_t , uint32_t > > ip_ranges ;
if ( 1 = = inet_pton ( AF_INET , " 192.168.0.0 " , & ( saNet . sin_addr ) ) & & 1 = = inet_pton ( AF_INET , " 255.255.0.0 " , & ( saMask . sin_addr ) ) )
ip_ranges . push_back ( { saNet . sin_addr . s_addr , saMask . sin_addr . s_addr } ) ;
if ( 1 = = inet_pton ( AF_INET , " 172.16.0.0 " , & ( saNet . sin_addr ) ) & & 1 = = inet_pton ( AF_INET , " 255.240.0.0 " , & ( saMask . sin_addr ) ) )
ip_ranges . push_back ( { saNet . sin_addr . s_addr , saMask . sin_addr . s_addr } ) ;
if ( 1 = = inet_pton ( AF_INET , " 10.0.0.0 " , & ( saNet . sin_addr ) ) & & 1 = = inet_pton ( AF_INET , " 255.0.0.0 " , & ( saMask . sin_addr ) ) )
ip_ranges . push_back ( { saNet . sin_addr . s_addr , saMask . sin_addr . s_addr } ) ;
if ( 1 = = inet_pton ( AF_INET , " 127.0.0.0 " , & ( saNet . sin_addr ) ) & & 1 = = inet_pton ( AF_INET , " 255.0.0.0 " , & ( saMask . sin_addr ) ) )
ip_ranges . push_back ( { saNet . sin_addr . s_addr , saMask . sin_addr . s_addr } ) ;
if ( 1 = = inet_pton ( AF_INET , " 169.254.0.0 " , & ( saNet . sin_addr ) ) & & 1 = = inet_pton ( AF_INET , " 255.255.0.0 " , & ( saMask . sin_addr ) ) )
ip_ranges . push_back ( { saNet . sin_addr . s_addr , saMask . sin_addr . s_addr } ) ;
return ip_ranges ;
}
bool isPrivateIP ( uint32_t ip ) {
static const std : : vector < std : : pair < uint32_t , uint32_t > > ip_ranges = InitPrivateIPRanges ( ) ;
for ( auto ipRange : ip_ranges ) {
if ( ( ip & ipRange . second ) = = ( ipRange . first & ipRange . second ) ) // We can just use ipRange.first directly if it's already correctly formatted
return true ;
}
return false ;
}
2013-11-10 01:26:31 +00:00
void getLocalMac ( SceNetEtherAddr * addr ) {
2013-11-28 11:38:45 +00:00
// Read MAC Address from config
uint8_t mac [ ETHER_ADDR_LEN ] = { 0 } ;
2019-11-09 23:23:19 +00:00
if ( PPSSPP_ID > 1 ) {
memset ( & mac , PPSSPP_ID , sizeof ( mac ) ) ;
}
else
2014-07-07 20:29:48 +00:00
if ( ! ParseMacAddress ( g_Config . sMACAddress . c_str ( ) , mac ) ) {
ERROR_LOG ( SCENET , " Error parsing mac address %s " , g_Config . sMACAddress . c_str ( ) ) ;
2013-11-28 11:38:45 +00:00
}
memcpy ( addr , mac , ETHER_ADDR_LEN ) ;
2013-11-10 01:26:31 +00:00
}
2014-06-24 16:43:03 +00:00
uint16_t getLocalPort ( int sock ) {
struct sockaddr_in localAddr ;
localAddr . sin_port = 0 ;
socklen_t addrLen = sizeof ( localAddr ) ;
getsockname ( sock , ( struct sockaddr * ) & localAddr , & addrLen ) ;
2014-07-31 18:55:42 +00:00
return ntohs ( localAddr . sin_port ) ;
}
2020-01-17 19:32:09 +00:00
int getSockMaxSize ( int udpsock ) {
int n = 1500 ; // Typical MTU size as default
2020-07-23 01:09:20 +00:00
# if defined(SO_MAX_MSG_SIZE) // May not be available on all platform
2020-01-17 19:32:09 +00:00
socklen_t m = sizeof ( n ) ;
getsockopt ( udpsock , SOL_SOCKET , SO_MAX_MSG_SIZE , ( char * ) & n , & m ) ;
2020-07-23 01:09:20 +00:00
# endif
2020-01-17 19:32:09 +00:00
return n ;
}
2014-07-31 18:55:42 +00:00
int getSockBufferSize ( int sock , int opt ) { // opt = SO_RCVBUF/SO_SNDBUF
int n = 16384 ;
socklen_t m = sizeof ( n ) ;
getsockopt ( sock , SOL_SOCKET , opt , ( char * ) & n , & m ) ; // in linux the value is twice of the value being set using setsockopt
return ( n / 2 ) ;
}
int setSockBufferSize ( int sock , int opt , int size ) { // opt = SO_RCVBUF/SO_SNDBUF
int n = size ; // 8192; //16384
return setsockopt ( sock , SOL_SOCKET , opt , ( char * ) & n , sizeof ( n ) ) ;
}
2020-01-17 19:32:09 +00:00
int setSockTimeout ( int sock , int opt , unsigned long timeout_usec ) { // opt = SO_SNDTIMEO/SO_RCVTIMEO
if ( timeout_usec > 0 & & timeout_usec < minSocketTimeoutUS ) timeout_usec = minSocketTimeoutUS ; // Override timeout for high latency multiplayer
# if defined(_WIN32)
unsigned long optval = timeout_usec / 1000UL ;
if ( timeout_usec > 0 & & optval = = 0 ) optval = 1 ; // Since there are games that use 100 usec timeout, we should set it to minimum value on Windows (1 msec) instead of using 0 (0 = indefinitely timeout)
2020-07-22 16:41:32 +00:00
# elif defined(__APPLE__)
struct timeval optval ;
optval . tv_sec = static_cast < long > ( timeout_usec ) / 1000000L ;
optval . tv_usec = static_cast < long > ( timeout_usec ) % 1000000L ;
2020-01-17 19:32:09 +00:00
# else
struct timeval optval = { static_cast < long > ( timeout_usec ) / 1000000L , static_cast < long > ( timeout_usec ) % 1000000L } ;
# endif
return setsockopt ( sock , SOL_SOCKET , opt , ( char * ) & optval , sizeof ( optval ) ) ;
}
int getSockNoDelay ( int tcpsock ) {
int opt = 0 ;
socklen_t optlen = sizeof ( opt ) ;
getsockopt ( tcpsock , IPPROTO_TCP , TCP_NODELAY , ( char * ) & opt , & optlen ) ;
return opt ;
}
int setSockNoDelay ( int tcpsock , int flag ) {
int opt = flag ;
return setsockopt ( tcpsock , IPPROTO_TCP , TCP_NODELAY , ( char * ) & opt , sizeof ( opt ) ) ;
}
2020-07-20 20:52:07 +00:00
# if !defined(TCP_KEEPIDLE)
# define TCP_KEEPIDLE TCP_KEEPALIVE //TCP_KEEPIDLE on Linux is equivalent to TCP_KEEPALIVE on macOS
# endif
2020-01-17 19:32:09 +00:00
int setSockKeepAlive ( int sock , bool keepalive , const int keepinvl , const int keepcnt , const int keepidle ) {
2020-01-04 00:41:54 +00:00
int optval = keepalive ? 1 : 0 ;
int optlen = sizeof ( optval ) ;
int result = setsockopt ( sock , SOL_SOCKET , SO_KEEPALIVE , ( char * ) & optval , optlen ) ;
if ( result = = 0 & & keepalive ) {
if ( getsockopt ( sock , SOL_SOCKET , SO_TYPE , ( char * ) & optval , ( socklen_t * ) & optlen ) = = 0 & & optval = = SOCK_STREAM ) {
optlen = sizeof ( optval ) ;
2020-01-17 19:32:09 +00:00
optval = keepidle ; //180 sec
setsockopt ( sock , IPPROTO_TCP , TCP_KEEPIDLE , ( char * ) & optval , optlen ) ;
optval = keepinvl ; //60 sec
setsockopt ( sock , IPPROTO_TCP , TCP_KEEPINTVL , ( char * ) & optval , optlen ) ;
2020-01-04 00:41:54 +00:00
optval = keepcnt ; //20
setsockopt ( sock , IPPROTO_TCP , TCP_KEEPCNT , ( char * ) & optval , optlen ) ;
}
}
return result ;
}
2014-07-31 18:55:42 +00:00
/**
* Return the Number of Players with the chosen Nickname in the Local Users current Network
* @ param nickname To - be - searched Nickname
* @ return Number of matching Players
*/
int getNicknameCount ( const char * nickname )
{
// Counter
int count = 0 ;
// Local Nickname Matches
2020-03-19 06:46:02 +00:00
if ( strncmp ( ( char * ) & parameter . nickname . data , nickname , ADHOCCTL_NICKNAME_LEN ) = = 0 ) count + + ;
2014-07-31 18:55:42 +00:00
// Peer Reference
SceNetAdhocctlPeerInfo * peer = friends ;
// Iterate Peers
for ( ; peer ! = NULL ; peer = peer - > next )
{
// Match found
2020-03-19 06:46:02 +00:00
if ( strncmp ( ( char * ) & peer - > nickname . data , nickname , ADHOCCTL_NICKNAME_LEN ) = = 0 ) count + + ;
2014-07-31 18:55:42 +00:00
}
// Return Result
return count ;
}
/**
* PDP Socket Counter
* @ return Number of internal PDP Sockets
*/
2019-12-23 17:04:03 +00:00
int getPDPSocketCount ( )
2014-07-31 18:55:42 +00:00
{
// Socket Counter
int counter = 0 ;
// Count Sockets
2019-12-23 17:04:03 +00:00
for ( int i = 0 ; i < 255 ; i + + ) if ( pdp [ i ] ! = NULL ) counter + + ;
2014-07-31 18:55:42 +00:00
// Return Socket Count
return counter ;
2014-06-24 16:43:03 +00:00
}
2019-12-23 17:04:03 +00:00
int getPTPSocketCount ( ) {
2014-07-31 18:55:42 +00:00
// Socket Counter
int counter = 0 ;
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
// Count Sockets
2019-12-23 17:04:03 +00:00
for ( int i = 0 ; i < 255 ; i + + ) if ( ptp [ i ] ! = NULL ) counter + + ;
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
// Return Socket Count
return counter ;
2013-11-10 01:26:31 +00:00
}
int initNetwork ( SceNetAdhocctlAdhocId * adhoc_id ) {
2019-12-23 17:04:03 +00:00
auto n = GetI18NCategory ( " Networking " ) ;
2014-07-31 18:55:42 +00:00
int iResult = 0 ;
metasocket = ( int ) INVALID_SOCKET ;
metasocket = socket ( AF_INET , SOCK_STREAM , IPPROTO_TCP ) ;
if ( metasocket = = INVALID_SOCKET ) {
ERROR_LOG ( SCENET , " Invalid socket " ) ;
2019-12-23 17:04:03 +00:00
return SOCKET_ERROR ;
2014-07-31 18:55:42 +00:00
}
2020-01-04 00:41:54 +00:00
setSockKeepAlive ( metasocket , true ) ;
2014-07-31 18:55:42 +00:00
struct sockaddr_in server_addr ;
server_addr . sin_family = AF_INET ;
server_addr . sin_port = htons ( SERVER_PORT ) ; //27312 // Maybe read this from config too
2013-11-10 01:26:31 +00:00
2014-03-03 08:08:32 +00:00
// Resolve dns
addrinfo * resultAddr ;
2015-02-04 12:41:21 +00:00
addrinfo * ptr ;
in_addr serverIp ;
2014-03-03 08:08:32 +00:00
serverIp . s_addr = INADDR_NONE ;
iResult = getaddrinfo ( g_Config . proAdhocServer . c_str ( ) , 0 , NULL , & resultAddr ) ;
if ( iResult ! = 0 ) {
2014-07-31 18:55:42 +00:00
ERROR_LOG ( SCENET , " DNS Error (%s) \n " , g_Config . proAdhocServer . c_str ( ) ) ;
2020-07-12 01:04:55 +00:00
host - > NotifyUserMessage ( n - > T ( " DNS Error connecting to " ) + g_Config . proAdhocServer , 2.0f , 0x0000ff ) ;
2014-03-03 08:08:32 +00:00
return iResult ;
2013-12-04 10:07:00 +00:00
}
2014-03-03 08:08:32 +00:00
for ( ptr = resultAddr ; ptr ! = NULL ; ptr = ptr - > ai_next ) {
switch ( ptr - > ai_family ) {
2013-12-04 10:07:00 +00:00
case AF_INET :
serverIp = ( ( sockaddr_in * ) ptr - > ai_addr ) - > sin_addr ;
2014-03-03 08:08:32 +00:00
break ;
2013-12-04 10:07:00 +00:00
}
}
2019-11-09 23:23:19 +00:00
freeaddrinfo ( resultAddr ) ;
// If Server is at localhost Try to Bind socket to specific adapter before connecting to prevent 2nd instance being recognized as already existing 127.0.0.1 by AdhocServer
// (may not works in WinXP/2003 for IPv4 due to "Weak End System" model)
if ( ( ( uint8_t * ) & serverIp . s_addr ) [ 0 ] = = 0x7f ) { // (serverIp.S_un.S_un_b.s_b1 == 0x7f)
int on = 1 ;
setsockopt ( metasocket , SOL_SOCKET , SO_REUSEADDR , ( const char * ) & on , sizeof ( on ) ) ;
setsockopt ( metasocket , SOL_SOCKET , SO_DONTROUTE , ( const char * ) & on , sizeof ( on ) ) ;
2020-02-25 09:29:06 +00:00
( ( struct sockaddr_in * ) & LocalhostIP ) - > sin_port = 0 ;
2019-11-09 23:23:19 +00:00
// Bind Local Address to Socket
2020-02-25 09:29:06 +00:00
iResult = bind ( metasocket , ( struct sockaddr * ) & LocalhostIP , sizeof ( sockaddr ) ) ;
2019-11-09 23:23:19 +00:00
if ( iResult = = SOCKET_ERROR ) {
2020-02-25 09:29:06 +00:00
ERROR_LOG ( SCENET , " Bind to alternate localhost[%s] failed(%i). " , inet_ntoa ( ( ( struct sockaddr_in * ) & LocalhostIP ) - > sin_addr ) , iResult ) ;
2020-07-12 01:04:55 +00:00
host - > NotifyUserMessage ( std : : string ( n - > T ( " Failed to Bind Localhost IP " ) ) + " " + inet_ntoa ( ( ( struct sockaddr_in * ) & LocalhostIP ) - > sin_addr ) , 2.0 , 0x0000ff ) ;
2019-11-09 23:23:19 +00:00
}
}
2014-07-31 18:55:42 +00:00
2020-03-19 06:46:02 +00:00
// Default/Initial Network Parameters
2014-07-31 18:55:42 +00:00
memset ( & parameter , 0 , sizeof ( parameter ) ) ;
2020-02-25 09:29:06 +00:00
strncpy ( ( char * ) & parameter . nickname . data , g_Config . sNickName . c_str ( ) , ADHOCCTL_NICKNAME_LEN ) ;
parameter . nickname . data [ ADHOCCTL_NICKNAME_LEN - 1 ] = 0 ;
2020-03-01 20:59:13 +00:00
parameter . channel = g_Config . iWlanAdhocChannel ;
2020-03-19 06:46:02 +00:00
// Assign a Valid Channel when connected to AP/Adhoc if it's Auto. JPCSP use 11 as default for Auto (Commonly for Auto: 1, 6, 11)
2020-03-01 20:59:13 +00:00
if ( parameter . channel = = PSP_SYSTEMPARAM_ADHOC_CHANNEL_AUTOMATIC ) parameter . channel = defaultWlanChannel ; // Faked Active channel to default channel
2014-07-31 18:55:42 +00:00
getLocalMac ( & parameter . bssid . mac_addr ) ;
2019-12-23 17:04:03 +00:00
// Default ProductId
product_code . type = adhoc_id - > type ;
memcpy ( product_code . data , adhoc_id - > data , ADHOCCTL_ADHOCID_LEN ) ;
2014-07-31 18:55:42 +00:00
2020-01-17 19:32:09 +00:00
// Switch to Nonblocking Behaviour
changeBlockingMode ( metasocket , 1 ) ;
2019-12-23 17:04:03 +00:00
// Connect to Adhoc Server
2013-12-04 10:07:00 +00:00
server_addr . sin_addr = serverIp ;
2020-01-17 19:32:09 +00:00
int errorcode = 0 ;
int cnt = 0 ;
while ( ( iResult = connect ( metasocket , ( sockaddr * ) & server_addr , sizeof ( server_addr ) ) ) = = SOCKET_ERROR & & ( errorcode = errno ) ! = EISCONN & & cnt < adhocDefaultTimeout ) {
sleep_ms ( 1 ) ;
cnt + + ;
}
// Switch back to Blocking Behaviour
changeBlockingMode ( metasocket , 0 ) ;
if ( iResult = = SOCKET_ERROR & & errorcode ! = EISCONN ) {
2015-01-04 11:20:49 +00:00
char buffer [ 512 ] ;
2020-01-17 19:32:09 +00:00
snprintf ( buffer , sizeof ( buffer ) , " Socket error (%i) when connecting to AdhocServer [%s/%s:%u] " , errorcode , g_Config . proAdhocServer . c_str ( ) , inet_ntoa ( server_addr . sin_addr ) , ntohs ( server_addr . sin_port ) ) ;
2015-01-04 11:20:49 +00:00
ERROR_LOG ( SCENET , " %s " , buffer ) ;
2020-07-12 01:04:55 +00:00
host - > NotifyUserMessage ( n - > T ( " Failed to connect to Adhoc Server " ) , 1.0f , 0x0000ff ) ;
2014-03-03 08:08:32 +00:00
return iResult ;
}
2014-07-31 18:55:42 +00:00
// Prepare Login Packet
SceNetAdhocctlLoginPacketC2S packet ;
packet . base . opcode = OPCODE_LOGIN ;
SceNetEtherAddr addres ;
getLocalMac ( & addres ) ;
packet . mac = addres ;
2020-02-25 09:29:06 +00:00
strncpy ( ( char * ) & packet . name . data , g_Config . sNickName . c_str ( ) , ADHOCCTL_NICKNAME_LEN ) ;
packet . name . data [ ADHOCCTL_NICKNAME_LEN - 1 ] = 0 ;
2014-07-31 18:55:42 +00:00
memcpy ( packet . game . data , adhoc_id - > data , ADHOCCTL_ADHOCID_LEN ) ;
int sent = send ( metasocket , ( char * ) & packet , sizeof ( packet ) , 0 ) ;
changeBlockingMode ( metasocket , 1 ) ; // Change to non-blocking
2015-02-04 12:41:21 +00:00
if ( sent > 0 ) {
2020-02-25 09:29:06 +00:00
socklen_t addrLen = sizeof ( LocalIP ) ;
memset ( & LocalIP , 0 , addrLen ) ;
getsockname ( metasocket , & LocalIP , & addrLen ) ;
2016-05-28 05:00:14 +00:00
host - > NotifyUserMessage ( n - > T ( " Network Initialized " ) , 1.0 ) ;
2014-07-31 18:55:42 +00:00
return 0 ;
}
else {
2019-12-23 17:04:03 +00:00
return SOCKET_ERROR ;
2014-07-31 18:55:42 +00:00
}
2013-11-10 01:26:31 +00:00
}
2014-12-06 15:01:34 +00:00
bool isBroadcastMAC ( const SceNetEtherAddr * addr ) {
2020-03-19 08:21:00 +00:00
return ( memcmp ( addr - > data , " \xFF \xFF \xFF \xFF \xFF \xFF " , ETHER_ADDR_LEN ) = = 0 ) ;
2013-11-10 01:26:31 +00:00
}
2014-12-06 15:01:34 +00:00
bool resolveIP ( uint32_t ip , SceNetEtherAddr * mac ) {
2014-07-31 18:55:42 +00:00
sockaddr_in addr ;
getLocalIp ( & addr ) ;
2015-09-06 17:10:08 +00:00
uint32_t localIp = addr . sin_addr . s_addr ;
2013-11-10 01:26:31 +00:00
2020-02-25 09:29:06 +00:00
if ( ip = = localIp | | ip = = ( ( sockaddr_in * ) & LocalhostIP ) - > sin_addr . s_addr ) {
2014-07-31 18:55:42 +00:00
getLocalMac ( mac ) ;
return true ;
}
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
// Multithreading Lock
peerlock . lock ( ) ;
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
// Peer Reference
SceNetAdhocctlPeerInfo * peer = friends ;
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
// Iterate Peers
for ( ; peer ! = NULL ; peer = peer - > next ) {
// Found Matching Peer
if ( peer - > ip_addr = = ip ) {
// Copy Data
* mac = peer - > mac_addr ;
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
// Multithreading Unlock
peerlock . unlock ( ) ;
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
// Return Success
return true ;
}
}
// Multithreading Unlock
peerlock . unlock ( ) ;
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
// Peer not found
return false ;
2013-11-10 01:26:31 +00:00
}
2014-12-11 04:42:37 +00:00
bool resolveMAC ( SceNetEtherAddr * mac , uint32_t * ip ) {
2014-07-31 18:55:42 +00:00
// Get Local MAC Address
SceNetEtherAddr localMac ;
getLocalMac ( & localMac ) ;
// Local MAC Requested
if ( memcmp ( & localMac , mac , sizeof ( SceNetEtherAddr ) ) = = 0 ) {
// Get Local IP Address
sockaddr_in sockAddr ;
getLocalIp ( & sockAddr ) ;
* ip = sockAddr . sin_addr . s_addr ;
return true ; // return succes
}
2013-11-10 01:26:31 +00:00
2014-07-31 18:55:42 +00:00
// Multithreading Lock
2017-03-18 21:33:43 +00:00
std : : lock_guard < std : : recursive_mutex > guard ( peerlock ) ;
2014-07-31 18:55:42 +00:00
// Peer Reference
SceNetAdhocctlPeerInfo * peer = friends ;
2014-12-06 15:01:34 +00:00
2014-07-31 18:55:42 +00:00
// Iterate Peers
for ( ; peer ! = NULL ; peer = peer - > next ) {
// Found Matching Peer
if ( memcmp ( & peer - > mac_addr , mac , sizeof ( SceNetEtherAddr ) ) = = 0 ) {
// Copy Data
* ip = peer - > ip_addr ;
2014-12-06 15:01:34 +00:00
2014-07-31 18:55:42 +00:00
// Return Success
return true ;
}
}
// Peer not found
return false ;
}
bool validNetworkName ( const SceNetAdhocctlGroupName * group_name ) {
// Result
2014-09-07 11:27:26 +00:00
bool valid = true ;
2014-07-31 18:55:42 +00:00
// Name given
if ( group_name ! = NULL ) {
// Iterate Name Characters
2019-12-23 17:04:03 +00:00
for ( int i = 0 ; i < ADHOCCTL_GROUPNAME_LEN & & valid ; i + + ) {
2014-07-31 18:55:42 +00:00
// End of Name
if ( group_name - > data [ i ] = = 0 ) break ;
// Not a digit
if ( group_name - > data [ i ] < ' 0 ' | | group_name - > data [ i ] > ' 9 ' ) {
// Not 'A' to 'Z'
if ( group_name - > data [ i ] < ' A ' | | group_name - > data [ i ] > ' Z ' ) {
// Not 'a' to 'z'
if ( group_name - > data [ i ] < ' a ' | | group_name - > data [ i ] > ' z ' ) {
// Invalid Name
valid = false ;
}
}
}
}
}
// Return Result
return valid ;
2013-11-10 01:26:31 +00:00
}
u64 join32 ( u32 num1 , u32 num2 ) {
2014-07-31 18:55:42 +00:00
return ( u64 ) num2 < < 32 | num1 ;
2013-11-10 01:26:31 +00:00
}
void split64 ( u64 num , int buff [ ] ) {
2014-07-31 18:55:42 +00:00
int num1 = ( int ) ( num & firstMask ) ;
int num2 = ( int ) ( ( num & secondMask ) > > 32 ) ;
buff [ 0 ] = num1 ;
buff [ 1 ] = num2 ;
}
2015-01-04 13:09:41 +00:00
const char * getMatchingEventStr ( int code ) {
const char * buf = NULL ;
2014-07-31 18:55:42 +00:00
switch ( code ) {
case PSP_ADHOC_MATCHING_EVENT_HELLO :
buf = " HELLO " ; break ;
case PSP_ADHOC_MATCHING_EVENT_REQUEST :
buf = " JOIN " ; break ;
case PSP_ADHOC_MATCHING_EVENT_LEAVE :
buf = " LEAVE " ; break ;
case PSP_ADHOC_MATCHING_EVENT_DENY :
buf = " REJECT " ; break ;
case PSP_ADHOC_MATCHING_EVENT_CANCEL :
buf = " CANCEL " ; break ;
case PSP_ADHOC_MATCHING_EVENT_ACCEPT :
buf = " ACCEPT " ; break ;
case PSP_ADHOC_MATCHING_EVENT_ESTABLISHED :
buf = " ESTABLISHED " ; break ;
case PSP_ADHOC_MATCHING_EVENT_TIMEOUT :
buf = " TIMEOUT " ; break ;
case PSP_ADHOC_MATCHING_EVENT_ERROR :
buf = " ERROR " ; break ;
case PSP_ADHOC_MATCHING_EVENT_BYE :
buf = " DISCONNECT " ; break ;
case PSP_ADHOC_MATCHING_EVENT_DATA :
buf = " DATA " ; break ;
case PSP_ADHOC_MATCHING_EVENT_DATA_ACK :
buf = " DATA_ACK " ; break ;
case PSP_ADHOC_MATCHING_EVENT_DATA_TIMEOUT :
buf = " DATA_TIMEOUT " ; break ;
case PSP_ADHOC_MATCHING_EVENT_INTERNAL_PING :
buf = " INTERNAL_PING " ; break ;
default :
buf = " UNKNOWN " ;
}
return buf ;
2013-11-10 01:26:31 +00:00
}
2014-07-31 18:55:42 +00:00
2015-01-04 13:09:41 +00:00
const char * getMatchingOpcodeStr ( int code ) {
const char * buf = NULL ;
2014-07-31 18:55:42 +00:00
switch ( code ) {
case PSP_ADHOC_MATCHING_PACKET_PING :
buf = " PING " ; break ;
case PSP_ADHOC_MATCHING_PACKET_HELLO :
buf = " HELLO " ; break ;
case PSP_ADHOC_MATCHING_PACKET_JOIN :
buf = " JOIN " ; break ;
case PSP_ADHOC_MATCHING_PACKET_ACCEPT :
buf = " ACCEPT " ; break ;
case PSP_ADHOC_MATCHING_PACKET_CANCEL :
buf = " CANCEL " ; break ;
case PSP_ADHOC_MATCHING_PACKET_BULK :
buf = " BULK " ; break ;
case PSP_ADHOC_MATCHING_PACKET_BULK_ABORT :
buf = " BULK_ABORT " ; break ;
case PSP_ADHOC_MATCHING_PACKET_BIRTH :
buf = " BIRTH " ; break ;
case PSP_ADHOC_MATCHING_PACKET_DEATH :
buf = " DEATH " ; break ;
case PSP_ADHOC_MATCHING_PACKET_BYE :
buf = " BYE " ; break ;
default :
buf = " UNKNOWN " ;
}
return buf ;
}