2013-09-06 22: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/.
2013-09-06 23:53:51 +00:00
// sceNetAdhoc
2013-12-05 19:37:01 +00:00
// This is a direct port of Coldbird's code from http://code.google.com/p/aemu/
2013-10-29 15:38:09 +00:00
// All credit goes to him!
2014-07-31 18:55:42 +00:00
# include "Core/Core.h"
2015-04-06 01:03:50 +00:00
# include "Core/MemMapHelpers.h"
2014-03-15 18:32:57 +00:00
# include "Common/ChunkFile.h"
2014-07-31 18:55:42 +00:00
# include "Core/MIPS/MIPSCodeUtils.h"
# include "Core/HLE/HLEHelperThread.h"
2014-03-15 18:22:19 +00:00
# include "Core/HLE/FunctionWrappers.h"
2014-03-30 00:02:41 +00:00
# include "Core/HLE/sceKernelThread.h"
2014-12-08 09:40:08 +00:00
# include "Core/HLE/sceNetAdhoc.h"
2014-07-31 18:55:42 +00:00
# include "Core/HLE/sceKernel.h"
# include "Core/HLE/sceKernelMemory.h"
# include "Core/HLE/sceKernelModule.h"
# include "Core/HLE/sceKernelInterrupt.h"
2014-03-15 18:22:19 +00:00
# include "Core/HLE/proAdhoc.h"
2014-07-31 18:55:42 +00:00
# include "Core/HLE/sceNet.h"
# include "Core/HLE/proAdhocServer.h"
2013-09-06 22:55:42 +00:00
2015-01-04 13:07:44 +00:00
# include "base/mutex.h"
2014-06-24 16:43:03 +00:00
// shared in sceNetAdhoc.h since it need to be used from sceNet.cpp also
2015-01-04 10:53:34 +00:00
// TODO: Make accessor functions instead, and throw all this state in a struct.
2014-07-31 18:55:42 +00:00
bool netAdhocInited ;
bool netAdhocctlInited ;
2015-01-04 10:53:34 +00:00
bool networkInited ;
2013-09-06 22:55:42 +00:00
static bool netAdhocMatchingInited ;
2014-07-31 18:55:42 +00:00
int netAdhocMatchingStarted = 0 ;
2013-09-06 22:55:42 +00:00
2014-07-31 18:55:42 +00:00
SceUID threadAdhocID ;
2015-01-04 13:07:44 +00:00
recursive_mutex adhocEvtMtx ;
std : : vector < std : : pair < u32 , u32 > > adhocctlEvents ;
std : : vector < u64 > matchingEvents ;
2015-04-27 14:53:19 +00:00
u32 dummyThreadHackAddr = 0 ;
2015-01-04 13:07:44 +00:00
u32_le dummyThreadCode [ 3 ] ;
2013-09-06 22:55:42 +00:00
2014-07-31 18:55:42 +00:00
std : : map < int , AdhocctlHandler > adhocctlHandlers ;
2013-09-06 22:55:42 +00:00
2014-07-31 18:55:42 +00:00
int matchingEventThread ( int matchingId ) ;
int matchingInputThread ( int matchingId ) ;
2013-09-06 22:55:42 +00:00
2013-11-05 16:36:01 +00:00
int sceNetAdhocTerm ( ) ;
int sceNetAdhocctlTerm ( ) ;
int sceNetAdhocMatchingTerm ( ) ;
2014-06-24 16:43:03 +00:00
int sceNetAdhocMatchingSetHelloOpt ( int matchingId , int optLenAddr , u32 optDataAddr ) ;
2013-11-05 16:36:01 +00:00
void __NetAdhocShutdown ( ) {
2014-08-24 07:22:55 +00:00
//Kill AdhocServer Thread
if ( adhocServerRunning ) {
adhocServerRunning = false ;
if ( adhocServerThread . joinable ( ) ) {
adhocServerThread . join ( ) ;
}
}
2013-12-04 16:41:59 +00:00
// Checks to avoid confusing logspam
2014-07-31 18:55:42 +00:00
if ( netAdhocMatchingInited ) {
sceNetAdhocMatchingTerm ( ) ;
2013-12-04 16:41:59 +00:00
}
if ( netAdhocctlInited ) {
sceNetAdhocctlTerm ( ) ;
}
2014-07-31 18:55:42 +00:00
if ( netAdhocInited ) {
sceNetAdhocTerm ( ) ;
2013-12-04 16:41:59 +00:00
}
2015-04-27 14:53:19 +00:00
if ( dummyThreadHackAddr ) {
kernelMemory . Free ( dummyThreadHackAddr ) ;
dummyThreadHackAddr = 0 ;
}
2013-09-06 22:55:42 +00:00
}
void __NetAdhocDoState ( PointerWrap & p ) {
2015-04-27 14:53:19 +00:00
auto s = p . Section ( " sceNetAdhoc " , 1 , 2 ) ;
2013-11-28 06:05:11 +00:00
if ( ! s )
return ;
2013-09-15 03:23:03 +00:00
2013-11-28 06:05:11 +00:00
p . Do ( netAdhocInited ) ;
p . Do ( netAdhocctlInited ) ;
p . Do ( netAdhocMatchingInited ) ;
p . Do ( adhocctlHandlers ) ;
2014-07-31 18:55:42 +00:00
2015-04-27 14:53:19 +00:00
if ( s > = 2 ) {
p . Do ( actionAfterMatchingMipsCall ) ;
__KernelRestoreActionType ( actionAfterMatchingMipsCall , AfterMatchingMipsCall : : Create ) ;
2014-07-31 18:55:42 +00:00
2015-04-27 14:53:19 +00:00
p . Do ( dummyThreadHackAddr ) ;
} else if ( p . mode = = p . MODE_READ ) {
// Previously, this wasn't being saved. It needs its own space.
if ( strcmp ( " dummythreadhack " , kernelMemory . GetBlockTag ( dummyThreadHackAddr ) ) ! = 0 ) {
u32 blockSize = sizeof ( dummyThreadCode ) ;
dummyThreadHackAddr = kernelMemory . Alloc ( blockSize , false , " dummythreadhack " ) ;
}
}
if ( dummyThreadHackAddr ) {
Memory : : Memcpy ( dummyThreadHackAddr , dummyThreadCode , sizeof ( dummyThreadCode ) ) ;
}
2013-09-06 22:55:42 +00:00
}
2015-01-04 13:07:44 +00:00
void __UpdateAdhocctlHandlers ( u32 flag , u32 error ) {
lock_guard adhocGuard ( adhocEvtMtx ) ;
adhocctlEvents . push_back ( { flag , error } ) ;
2013-10-26 14:47:52 +00:00
}
2014-07-31 18:55:42 +00:00
// TODO: MipsCall needs to be called from it's own PSP Thread instead of from any random PSP Thread
void __UpdateMatchingHandler ( u64 ArgsPtr ) {
2015-01-04 13:07:44 +00:00
lock_guard adhocGuard ( adhocEvtMtx ) ;
matchingEvents . push_back ( ArgsPtr ) ;
2014-07-31 18:55:42 +00:00
}
2014-12-08 09:40:08 +00:00
static int getBlockingFlag ( int id ) {
2013-11-25 01:57:08 +00:00
# ifdef _MSC_VER
2013-11-28 06:05:11 +00:00
return 0 ;
2013-11-25 01:57:08 +00:00
# else
2013-11-28 06:05:11 +00:00
int sockflag = fcntl ( id , F_GETFL , O_NONBLOCK ) ;
return sockflag & O_NONBLOCK ;
2013-11-25 01:57:08 +00:00
# endif
}
2014-07-31 18:55:42 +00:00
void __NetAdhocInit ( ) {
friendFinderRunning = false ;
netAdhocInited = false ;
netAdhocctlInited = false ;
netAdhocMatchingInited = false ;
adhocctlHandlers . clear ( ) ;
2014-08-05 12:05:08 +00:00
__AdhocServerInit ( ) ;
2015-01-04 13:07:44 +00:00
dummyThreadCode [ 0 ] = MIPS_MAKE_SYSCALL ( " sceNetAdhoc " , " __NetTriggerCallbacks " ) ;
dummyThreadCode [ 1 ] = MIPS_MAKE_B ( - 2 ) ;
dummyThreadCode [ 2 ] = MIPS_MAKE_NOP ( ) ;
2014-07-31 18:55:42 +00:00
u32 blockSize = sizeof ( dummyThreadCode ) ;
dummyThreadHackAddr = kernelMemory . Alloc ( blockSize , false , " dummythreadhack " ) ;
Memory : : Memcpy ( dummyThreadHackAddr , dummyThreadCode , sizeof ( dummyThreadCode ) ) ; // This area will be cleared again after loading an old savestate :(
actionAfterMatchingMipsCall = __KernelRegisterActionType ( AfterMatchingMipsCall : : Create ) ;
2014-08-23 20:46:28 +00:00
// Create built-in AdhocServer Thread
if ( g_Config . bEnableWlan & & g_Config . bEnableAdhocServer ) {
adhocServerRunning = true ;
adhocServerThread = std : : thread ( proAdhocServerThread , SERVER_PORT ) ;
}
2014-07-31 18:55:42 +00:00
}
u32 sceNetAdhocInit ( ) {
2013-11-28 06:05:11 +00:00
// Library uninitialized
2014-06-24 16:43:03 +00:00
INFO_LOG ( SCENET , " sceNetAdhocInit() at %08x " , currentMIPS - > pc ) ;
2013-12-05 19:43:30 +00:00
if ( ! netAdhocInited ) {
2013-11-28 06:05:11 +00:00
// Clear Translator Memory
memset ( & pdp , 0 , sizeof ( pdp ) ) ;
memset ( & ptp , 0 , sizeof ( ptp ) ) ;
2013-09-06 22:55:42 +00:00
2013-11-28 06:05:11 +00:00
// Library initialized
netAdhocInited = true ;
2013-10-26 14:47:52 +00:00
2014-07-31 18:55:42 +00:00
// Create fake PSP Thread for callback
// TODO: Should use a separated threads for friendFinder, matchingEvent, and matchingInput and created on AdhocctlInit & AdhocMatchingStart instead of here
# define PSP_THREAD_ATTR_KERNEL 0x00001000 // PSP_THREAD_ATTR_KERNEL is located in sceKernelThread.cpp instead of sceKernelThread.h :(
//threadAdhocID = __KernelCreateThreadInternal("AdhocThread", __KernelGetCurThreadModuleId(), dummyThreadHackAddr, 0x30, 4096, PSP_THREAD_ATTR_KERNEL);
2015-01-04 13:07:44 +00:00
threadAdhocID = __KernelCreateThread ( " AdhocThread " , __KernelGetCurThreadModuleId ( ) , dummyThreadHackAddr , 0x10 , 0x1000 , 0 , PSP_THREAD_ATTR_KERNEL ) ;
2014-07-31 18:55:42 +00:00
if ( threadAdhocID > 0 ) {
__KernelStartThread ( threadAdhocID , 0 , 0 ) ;
}
2013-11-28 06:05:11 +00:00
// Return Success
return 0 ;
}
// Already initialized
return ERROR_NET_ADHOC_ALREADY_INITIALIZED ;
2013-09-06 22:55:42 +00:00
}
2014-12-08 09:40:08 +00:00
static u32 sceNetAdhocctlInit ( int stackSize , int prio , u32 productAddr ) {
2014-06-24 16:43:03 +00:00
INFO_LOG ( SCENET , " sceNetAdhocctlInit(%i, %i, %08x) at %08x " , stackSize , prio , productAddr , currentMIPS - > pc ) ;
2014-07-31 18:55:42 +00:00
2015-01-04 10:53:34 +00:00
if ( netAdhocctlInited )
return ERROR_NET_ADHOCCTL_ALREADY_INITIALIZED ;
2014-07-31 18:55:42 +00:00
2015-01-04 10:53:34 +00:00
if ( g_Config . bEnableWlan ) {
if ( initNetwork ( ( SceNetAdhocctlAdhocId * ) Memory : : GetPointer ( productAddr ) ) = = 0 ) {
if ( ! friendFinderRunning ) {
friendFinderRunning = true ;
friendFinderThread = std : : thread ( friendFinder ) ;
}
networkInited = true ;
} else {
WARN_LOG ( SCENET , " sceNetAdhocctlInit: Failed to init the network but faking success " ) ;
networkInited = false ; // TODO: What needs to check this? Pretty much everything? Maybe we should just set netAdhocctlInited to false..
2014-09-06 22:54:46 +00:00
}
}
2015-01-04 10:53:34 +00:00
2014-09-07 11:27:26 +00:00
netAdhocctlInited = true ; //needed for cleanup during AdhocctlTerm even when it failed to connect to Adhoc Server (since it's being faked as success)
2013-11-28 06:05:11 +00:00
return 0 ;
2013-09-06 22:55:42 +00:00
}
2014-12-08 09:40:08 +00:00
static int sceNetAdhocctlGetState ( u32 ptrToStatus ) {
2013-10-28 20:30:25 +00:00
// Library initialized
2013-12-05 19:43:30 +00:00
if ( netAdhocctlInited ) {
2013-10-28 20:30:25 +00:00
// Valid Arguments
2013-12-05 19:43:30 +00:00
if ( Memory : : IsValidAddress ( ptrToStatus ) ) {
2013-10-28 20:30:25 +00:00
// Return Thread Status
2013-12-04 10:07:00 +00:00
Memory : : Write_U32 ( threadStatus , ptrToStatus ) ;
2013-10-28 20:30:25 +00:00
// Return Success
return 0 ;
}
// Invalid Arguments
return ERROR_NET_ADHOCCTL_INVALID_ARG ;
}
// Library uninitialized
return ERROR_NET_ADHOCCTL_NOT_INITIALIZED ;
2013-10-26 14:47:52 +00:00
}
/**
* Adhoc Emulator PDP Socket Creator
* @ param saddr Local MAC ( Unused )
* @ param sport Local Binding Port
* @ param bufsize Socket Buffer Size
* @ param flag Bitflags ( Unused )
* @ return Socket ID > 0 on success or . . . ADHOC_NOT_INITIALIZED , ADHOC_INVALID_ARG , ADHOC_SOCKET_ID_NOT_AVAIL , ADHOC_INVALID_ADDR , ADHOC_PORT_NOT_AVAIL , ADHOC_INVALID_PORT , ADHOC_PORT_IN_USE , NET_NO_SPACE
*/
2014-06-24 16:43:03 +00:00
// When choosing AdHoc menu in Wipeout Pulse sometimes it's saying that "WLAN is turned off" on game screen and getting "kUnityCommandCode_MediaDisconnected" error in the Log Console when calling sceNetAdhocPdpCreate, probably it needed to wait something from the thread before calling this (ie. need to receives 7 bytes from adhoc server 1st?)
2014-12-08 09:40:08 +00:00
static int sceNetAdhocPdpCreate ( const char * mac , u32 port , int bufferSize , u32 unknown ) {
2014-07-31 18:55:42 +00:00
INFO_LOG ( SCENET , " sceNetAdhocPdpCreate(%s, %u, %u, %u) at %08x " , mac , port , bufferSize , unknown , currentMIPS - > pc ) ;
2013-12-04 10:07:00 +00:00
if ( ! g_Config . bEnableWlan ) {
return - 1 ;
}
2014-06-24 16:43:03 +00:00
int retval = ERROR_NET_ADHOC_NOT_INITIALIZED ;
2013-11-28 06:05:11 +00:00
// Library is initialized
SceNetEtherAddr * saddr = ( SceNetEtherAddr * ) mac ;
2013-12-05 19:43:30 +00:00
if ( netAdhocInited ) {
2013-11-28 06:05:11 +00:00
// Valid Arguments are supplied
2013-12-05 19:43:30 +00:00
if ( mac ! = NULL & & bufferSize > 0 ) {
2013-11-28 06:05:11 +00:00
// Valid MAC supplied
2013-12-05 19:43:30 +00:00
if ( isLocalMAC ( saddr ) ) {
2013-11-28 06:05:11 +00:00
//// Unused Port supplied
2013-12-05 19:43:30 +00:00
//if (!_IsPDPPortInUse(port)) {}
2013-11-28 06:05:11 +00:00
//
//// Port is in use by another PDP Socket
//return ERROR_NET_ADHOC_PORT_IN_USE;
// Create Internet UDP Socket
2014-09-07 11:27:26 +00:00
int usocket = ( int ) INVALID_SOCKET ;
usocket = socket ( AF_INET , SOCK_DGRAM , IPPROTO_UDP ) ;
2013-11-28 06:05:11 +00:00
// Valid Socket produced
2013-12-05 19:43:30 +00:00
if ( usocket ! = INVALID_SOCKET ) {
2014-07-31 18:55:42 +00:00
// Change socket buffer size when necessary
if ( getSockBufferSize ( usocket , SO_SNDBUF ) < bufferSize ) setSockBufferSize ( usocket , SO_SNDBUF , bufferSize ) ;
if ( getSockBufferSize ( usocket , SO_RCVBUF ) < bufferSize ) setSockBufferSize ( usocket , SO_RCVBUF , bufferSize ) ;
// Enable Port Re-use, this will allow binding to an already used port, but only one of them can read the data (shared receive buffer?)
int one = 1 ;
setsockopt ( usocket , SOL_SOCKET , SO_REUSEADDR , ( const char * ) & one , sizeof ( one ) ) ; // NO idea if we need this
2013-11-28 06:05:11 +00:00
// Binding Information for local Port
sockaddr_in addr ;
addr . sin_family = AF_INET ;
addr . sin_addr . s_addr = INADDR_ANY ;
2014-07-31 18:55:42 +00:00
//if (port < 7) addr.sin_port = htons(port + 1341); else // <= 443
2013-11-28 06:05:11 +00:00
addr . sin_port = htons ( port ) ; // This not safe in any way...
2014-06-24 16:43:03 +00:00
// The port might be under 1024 (ie. GTA:VCS use port 1, Ford Street Racing use port 0 (UNUSED_PORT), etc) and already used by other application/host OS, should we add 1024 to the port whenever it tried to use an already used port?
2013-11-28 06:05:11 +00:00
// Bound Socket to local Port
2014-06-24 16:43:03 +00:00
int iResult = bind ( usocket , ( sockaddr * ) & addr , sizeof ( addr ) ) ;
/*if (iResult == SOCKET_ERROR && errno == 10048) { //Forcing PdpCreate to be successfull using a different Port might not works and might affect other players sharing the same IP due to "deleteFriendByIP" (should delete by MAC instead of IP)
addr . sin_port = 0 ; //UNUSED_PORT
iResult = bind ( usocket , ( sockaddr * ) & addr , sizeof ( addr ) ) ;
WARN_LOG ( SCENET , " Port %u is already used, replaced with UNUSED_PORT(%u) " , port , ntohs ( addr . sin_port ) ) ;
} */
if ( iResult = = 0 ) {
2013-11-28 06:05:11 +00:00
// Allocate Memory for Internal Data
SceNetAdhocPdpStat * internal = ( SceNetAdhocPdpStat * ) malloc ( sizeof ( SceNetAdhocPdpStat ) ) ;
// Allocated Memory
2013-12-05 19:43:30 +00:00
if ( internal ! = NULL ) {
2013-11-28 06:05:11 +00:00
// Clear Memory
memset ( internal , 0 , sizeof ( SceNetAdhocPdpStat ) ) ;
// Find Free Translator Index
2013-12-05 19:43:30 +00:00
int i = 0 ; for ( ; i < 255 ; i + + ) if ( pdp [ i ] = = NULL ) break ;
2013-11-28 06:05:11 +00:00
// Found Free Translator Index
2013-12-05 19:43:30 +00:00
if ( i < 255 ) {
2013-11-28 06:05:11 +00:00
// Fill in Data
internal - > id = usocket ;
internal - > laddr = * saddr ;
2014-07-31 18:55:42 +00:00
internal - > lport = getLocalPort ( usocket ) ; //should use the port given to the socket (in case it's UNUSED_PORT port) isn't?
2013-11-28 06:05:11 +00:00
internal - > rcv_sb_cc = bufferSize ;
// Link Socket to Translator ID
pdp [ i ] = internal ;
// Forward Port on Router
//sceNetPortOpen("UDP", sport); // I need to figure out how to use this in windows/linux
2014-06-24 16:43:03 +00:00
2013-11-28 06:05:11 +00:00
// Success
return i + 1 ;
2014-06-24 16:43:03 +00:00
}
2013-11-28 06:05:11 +00:00
// Free Memory for Internal Data
free ( internal ) ;
}
2014-06-24 16:43:03 +00:00
retval = ERROR_NET_NO_SPACE ;
}
else {
retval = ERROR_NET_ADHOC_PORT_IN_USE ;
if ( iResult = = SOCKET_ERROR ) {
ERROR_LOG ( SCENET , " Socket error (%i) when binding port %u " , errno , ntohs ( addr . sin_port ) ) ;
}
2013-11-28 06:05:11 +00:00
}
// Close Socket
closesocket ( usocket ) ;
2014-06-24 16:43:03 +00:00
return retval ;
2013-11-28 06:05:11 +00:00
}
// Default to No-Space Error
return ERROR_NET_NO_SPACE ;
}
// Invalid MAC supplied
2014-06-24 16:43:03 +00:00
//return ERROR_NET_ADHOC_INVALID_ADDR;
2013-11-28 06:05:11 +00:00
}
// Invalid Arguments were supplied
return ERROR_NET_ADHOC_INVALID_ARG ;
}
// Library is uninitialized
return ERROR_NET_ADHOC_NOT_INITIALIZED ;
2013-09-06 22:55:42 +00:00
}
2013-10-28 20:30:25 +00:00
/**
* Get Adhoc Parameter
* @ param parameter OUT : Adhoc Parameter
* @ return 0 on success or . . . ADHOCCTL_NOT_INITIALIZED , ADHOCCTL_INVALID_ARG
*/
2014-12-08 09:40:08 +00:00
static int sceNetAdhocctlGetParameter ( u32 paramAddr ) {
2014-07-31 18:55:42 +00:00
DEBUG_LOG ( SCENET , " sceNetAdhocctlGetParameter(%08x) " , paramAddr ) ;
2013-12-04 10:07:00 +00:00
if ( ! g_Config . bEnableWlan ) {
return ERROR_NET_ADHOCCTL_DISCONNECTED ;
}
2013-11-28 06:05:11 +00:00
// Library initialized
2013-12-05 19:43:30 +00:00
if ( netAdhocctlInited ) {
2013-11-28 06:05:11 +00:00
// Valid Arguments
2013-12-05 19:43:30 +00:00
if ( Memory : : IsValidAddress ( paramAddr ) ) {
2013-11-28 06:05:11 +00:00
// Copy Parameter
Memory : : WriteStruct ( paramAddr , & parameter ) ;
// Return Success
return 0 ;
}
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Invalid Arguments
return ERROR_NET_ADHOCCTL_INVALID_ARG ;
}
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Library uninitialized
return ERROR_NET_ADHOCCTL_NOT_INITIALIZED ;
2013-10-26 14:47:52 +00:00
}
/**
* Adhoc Emulator PDP Send Call
* @ param id Socket File Descriptor
* @ param daddr Target MAC Address
* @ param dport Target Port
* @ param data Data Payload
* @ param len Payload Length
* @ param timeout Send Timeout
* @ param flag Nonblocking Flag
* @ return 0 on success or . . . ADHOC_INVALID_ARG , ADHOC_NOT_INITIALIZED , ADHOC_INVALID_SOCKET_ID , ADHOC_SOCKET_DELETED , ADHOC_INVALID_ADDR , ADHOC_INVALID_PORT , ADHOC_INVALID_DATALEN , ADHOC_SOCKET_ALERTED , ADHOC_TIMEOUT , ADHOC_THREAD_ABORTED , ADHOC_WOULD_BLOCK , NET_NO_SPACE , NET_INTERNAL
*/
2014-12-08 09:40:08 +00:00
static int sceNetAdhocPdpSend ( int id , const char * mac , u32 port , void * data , int len , int timeout , int flag ) {
2014-07-31 18:55:42 +00:00
DEBUG_LOG ( SCENET , " sceNetAdhocPdpSend(%i, %s, %i, %p, %i, %i, %i) " , id , mac , port , data , len , timeout , flag ) ;
2013-12-04 10:07:00 +00:00
if ( ! g_Config . bEnableWlan ) {
return - 1 ;
}
2013-11-28 06:05:11 +00:00
SceNetEtherAddr * daddr = ( SceNetEtherAddr * ) mac ;
2015-09-06 17:10:08 +00:00
uint16_t dport = ( uint16_t ) port ;
2014-07-31 18:55:42 +00:00
//if (dport < 7) dport += 1341;
2013-12-04 10:07:00 +00:00
// Really should flatten this with early outs, all this indentation is making me dizzy.
2013-11-28 06:05:11 +00:00
// Library is initialized
2013-12-05 19:43:30 +00:00
if ( netAdhocInited ) {
2013-11-28 06:05:11 +00:00
// Valid Port
2013-12-05 19:43:30 +00:00
if ( dport ! = 0 ) {
2013-11-28 06:05:11 +00:00
// Valid Data Length
2014-06-24 16:43:03 +00:00
if ( len > = 0 ) { // should we allow 0 size packet (for ping) ?
2013-11-28 06:05:11 +00:00
// Valid Socket ID
2013-12-05 19:43:30 +00:00
if ( id > 0 & & id < = 255 & & pdp [ id - 1 ] ! = NULL ) {
2013-11-28 06:05:11 +00:00
// Cast Socket
SceNetAdhocPdpStat * socket = pdp [ id - 1 ] ;
// Valid Data Buffer
2013-12-05 19:43:30 +00:00
if ( data ! = NULL ) {
2013-11-28 06:05:11 +00:00
// Valid Destination Address
2013-12-05 19:43:30 +00:00
if ( daddr ! = NULL ) {
2013-11-28 06:05:11 +00:00
// Log Destination
// Schedule Timeout Removal
2013-12-05 19:43:30 +00:00
if ( flag ) timeout = 0 ;
2013-11-28 06:05:11 +00:00
// Apply Send Timeout Settings to Socket
setsockopt ( socket - > id , SOL_SOCKET , SO_SNDTIMEO , ( const char * ) & timeout , sizeof ( timeout ) ) ;
// Single Target
2013-12-05 19:43:30 +00:00
if ( ! isBroadcastMAC ( daddr ) ) {
2013-11-28 06:05:11 +00:00
// Fill in Target Structure
sockaddr_in target ;
target . sin_family = AF_INET ;
target . sin_port = htons ( dport ) ;
// Get Peer IP
2014-12-06 15:01:34 +00:00
if ( resolveMAC ( ( SceNetEtherAddr * ) daddr , ( uint32_t * ) & target . sin_addr . s_addr ) ) {
2013-11-28 06:05:11 +00:00
// Acquire Network Lock
//_acquireNetworkLock();
// Send Data
changeBlockingMode ( socket - > id , flag ) ;
int sent = sendto ( socket - > id , ( const char * ) data , len , 0 , ( sockaddr * ) & target , sizeof ( target ) ) ;
2014-06-26 10:50:37 +00:00
int error = errno ;
2014-06-24 16:43:03 +00:00
if ( sent = = SOCKET_ERROR ) {
2014-07-31 18:55:42 +00:00
DEBUG_LOG ( SCENET , " Socket Error (%i) on sceNetAdhocPdpSend[%i:%u->%u] (size=%i) " , error , id , getLocalPort ( socket - > id ) , ntohs ( target . sin_port ) , len ) ;
2014-06-24 16:43:03 +00:00
}
2013-11-28 06:05:11 +00:00
changeBlockingMode ( socket - > id , 0 ) ;
// Free Network Lock
//_freeNetworkLock();
2014-06-24 16:43:03 +00:00
uint8_t * sip = ( uint8_t * ) & target . sin_addr . s_addr ;
2013-11-28 06:05:11 +00:00
// Sent Data
2013-12-05 19:43:30 +00:00
if ( sent = = len ) {
2014-07-31 18:55:42 +00:00
DEBUG_LOG ( SCENET , " sceNetAdhocPdpSend[%i:%u]: Sent %u bytes to %u.%u.%u.%u:%u \n " , id , getLocalPort ( socket - > id ) , sent , sip [ 0 ] , sip [ 1 ] , sip [ 2 ] , sip [ 3 ] , ntohs ( target . sin_port ) ) ;
2014-06-24 16:43:03 +00:00
2013-11-28 06:05:11 +00:00
// Success
2014-06-25 13:29:42 +00:00
return 0 ;
2014-06-24 16:43:03 +00:00
}
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Blocking Situation
2013-12-05 19:43:30 +00:00
if ( flag ) return ERROR_NET_ADHOC_WOULD_BLOCK ;
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Timeout
2014-06-24 16:43:03 +00:00
return ERROR_NET_ADHOC_TIMEOUT ; //-1;
2013-11-28 06:05:11 +00:00
}
}
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Broadcast Target
else {
// Acquire Network Lock
//_acquireNetworkLock();
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
# ifdef BROADCAST_TO_LOCALHOST
//// Get Local IP Address
2013-12-05 19:43:30 +00:00
//union SceNetApctlInfo info; if (sceNetApctlGetInfo(PSP_NET_APCTL_INFO_IP, &info) == 0) {
2013-11-28 06:05:11 +00:00
// // Fill in Target Structure
// SceNetInetSockaddrIn target;
// target.sin_family = AF_INET;
// sceNetInetInetAton(info.ip, &target.sin_addr);
// target.sin_port = sceNetHtons(dport);
//
// // Send Data
// sceNetInetSendto(socket->id, data, len, ((flag != 0) ? (INET_MSG_DONTWAIT) : (0)), (SceNetInetSockaddr *)&target, sizeof(target));
//}
# endif
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Acquire Peer Lock
peerlock . lock ( ) ;
// Iterate Peers
SceNetAdhocctlPeerInfo * peer = friends ;
2013-12-05 19:43:30 +00:00
for ( ; peer ! = NULL ; peer = peer - > next ) {
2014-07-31 18:55:42 +00:00
// Skip timed out friends
if ( peer - > last_recv = = 0 ) continue ;
2013-11-28 06:05:11 +00:00
// Fill in Target Structure
sockaddr_in target ;
target . sin_family = AF_INET ;
target . sin_addr . s_addr = peer - > ip_addr ;
target . sin_port = htons ( dport ) ;
// Send Data
changeBlockingMode ( socket - > id , flag ) ;
2014-06-24 16:43:03 +00:00
int sent = sendto ( socket - > id , ( const char * ) data , len , 0 , ( sockaddr * ) & target , sizeof ( target ) ) ;
2014-06-26 10:50:37 +00:00
int error = errno ;
2014-06-24 16:43:03 +00:00
if ( sent = = SOCKET_ERROR ) {
2014-07-31 18:55:42 +00:00
DEBUG_LOG ( SCENET , " Socket Error (%i) on sceNetAdhocPdpSend[%i:%u->%u](BC) [size=%i] " , error , id , getLocalPort ( socket - > id ) , ntohs ( target . sin_port ) , len ) ;
2014-06-24 16:43:03 +00:00
}
2013-11-28 06:05:11 +00:00
changeBlockingMode ( socket - > id , 0 ) ;
2014-06-24 16:43:03 +00:00
if ( sent > = 0 ) {
uint8_t * sip = ( uint8_t * ) & target . sin_addr . s_addr ;
2014-07-31 18:55:42 +00:00
DEBUG_LOG ( SCENET , " sceNetAdhocPdpSend[%i:%u](BC): Sent %u bytes to %u.%u.%u.%u:%u \n " , id , getLocalPort ( socket - > id ) , sent , sip [ 0 ] , sip [ 1 ] , sip [ 2 ] , sip [ 3 ] , ntohs ( target . sin_port ) ) ;
2014-06-24 16:43:03 +00:00
}
2013-11-28 06:05:11 +00:00
}
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Free Peer Lock
peerlock . unlock ( ) ;
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Free Network Lock
//_freeNetworkLock();
2013-10-26 14:47:52 +00:00
2014-06-25 13:29:42 +00:00
// Success, Broadcast never fails!
return 0 ;
2013-11-28 06:05:11 +00:00
}
}
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Invalid Destination Address
return ERROR_NET_ADHOC_INVALID_ADDR ;
}
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Invalid Argument
return ERROR_NET_ADHOC_INVALID_ARG ;
}
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Invalid Socket ID
return ERROR_NET_ADHOC_INVALID_SOCKET_ID ;
}
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Invalid Data Length
return ERROR_NET_ADHOC_INVALID_DATALEN ;
}
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Invalid Destination Port
return ERROR_NET_ADHOC_INVALID_PORT ;
}
// Library is uninitialized
return ERROR_NET_ADHOC_NOT_INITIALIZED ;
2013-10-26 14:47:52 +00:00
}
2014-06-26 10:50:37 +00:00
2013-10-26 14:47:52 +00:00
/**
* Adhoc Emulator PDP Receive Call
* @ param id Socket File Descriptor
* @ param saddr OUT : Source MAC Address
* @ param sport OUT : Source Port
* @ param buf OUT : Received Data
* @ param len IN : Buffer Size OUT : Received Data Length
* @ param timeout Receive Timeout
* @ param flag Nonblocking Flag
* @ return 0 on success or . . . ADHOC_INVALID_ARG , ADHOC_NOT_INITIALIZED , ADHOC_INVALID_SOCKET_ID , ADHOC_SOCKET_DELETED , ADHOC_SOCKET_ALERTED , ADHOC_WOULD_BLOCK , ADHOC_TIMEOUT , ADHOC_NOT_ENOUGH_SPACE , ADHOC_THREAD_ABORTED , NET_INTERNAL
*/
2014-12-08 09:40:08 +00:00
static int sceNetAdhocPdpRecv ( int id , void * addr , void * port , void * buf , void * dataLength , u32 timeout , int flag ) {
2014-06-24 16:43:03 +00:00
DEBUG_LOG ( SCENET , " sceNetAdhocPdpRecv(%i, %p, %p, %p, %p, %i, %i) at %08x " , id , addr , port , buf , dataLength , timeout , flag , currentMIPS - > pc ) ;
2013-12-04 10:07:00 +00:00
if ( ! g_Config . bEnableWlan ) {
return - 1 ;
}
2013-11-28 06:05:11 +00:00
SceNetEtherAddr * saddr = ( SceNetEtherAddr * ) addr ;
2014-06-26 10:50:37 +00:00
uint16_t * sport = ( uint16_t * ) port ; //Looking at Quake3 sourcecode (net_adhoc.c) this is an "int" (32bit) but changing here to 32bit will cause FF-Type0 to see duplicated Host (thinking it was from a different host)
2013-11-28 06:05:11 +00:00
int * len = ( int * ) dataLength ;
2013-12-05 19:43:30 +00:00
if ( netAdhocInited ) {
2013-11-28 06:05:11 +00:00
// Valid Socket ID
2013-12-05 19:43:30 +00:00
if ( id > 0 & & id < = 255 & & pdp [ id - 1 ] ! = NULL ) {
2013-11-28 06:05:11 +00:00
// Cast Socket
SceNetAdhocPdpStat * socket = pdp [ id - 1 ] ;
// Valid Arguments
2014-06-26 10:50:37 +00:00
if ( saddr ! = NULL & & port ! = NULL & & buf ! = NULL & & len ! = NULL & & * len > 0 ) {
2013-10-26 14:47:52 +00:00
# ifndef PDP_DIRTY_MAGIC
2013-11-28 06:05:11 +00:00
// Schedule Timeout Removal
2013-12-05 19:43:30 +00:00
if ( flag = = 1 ) timeout = 0 ;
2013-10-26 14:47:52 +00:00
# else
2013-11-28 06:05:11 +00:00
// Nonblocking Simulator
int wouldblock = 0 ;
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Minimum Timeout
uint32_t mintimeout = 250000 ;
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Nonblocking Call
2013-12-05 19:43:30 +00:00
if ( flag = = 1 ) {
2013-11-28 06:05:11 +00:00
// Erase Nonblocking Flag
flag = 0 ;
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Set Wouldblock Behaviour
wouldblock = 1 ;
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Set Minimum Timeout (250ms)
2013-12-05 19:43:30 +00:00
if ( timeout < mintimeout ) timeout = mintimeout ;
2013-11-28 06:05:11 +00:00
}
2013-10-26 14:47:52 +00:00
# endif
2013-11-28 06:05:11 +00:00
// Apply Receive Timeout Settings to Socket
setsockopt ( socket - > id , SOL_SOCKET , SO_RCVTIMEO , ( const char * ) & timeout , sizeof ( timeout ) ) ;
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Sender Address
sockaddr_in sin ;
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Set Address Length (so we get the sender ip)
socklen_t sinlen = sizeof ( sin ) ;
//sin.sin_len = (uint8_t)sinlen;
2014-06-26 10:50:37 +00:00
2013-11-28 06:05:11 +00:00
// Acquire Network Lock
//_acquireNetworkLock();
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Receive Data
2014-07-31 18:55:42 +00:00
changeBlockingMode ( socket - > id , flag ) ;
2013-11-28 06:05:11 +00:00
int received = recvfrom ( socket - > id , ( char * ) buf , * len , 0 , ( sockaddr * ) & sin , & sinlen ) ;
2014-06-26 10:50:37 +00:00
int error = errno ;
if ( received = = SOCKET_ERROR ) {
2014-07-31 18:55:42 +00:00
VERBOSE_LOG ( SCENET , " Socket Error (%i) on sceNetAdhocPdpRecv [size=%i] " , error , * len ) ;
2014-06-26 10:50:37 +00:00
}
2014-06-24 16:43:03 +00:00
changeBlockingMode ( socket - > id , 0 ) ;
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Received Data
2014-06-26 10:50:37 +00:00
if ( received > = 0 ) {
2014-06-24 16:43:03 +00:00
uint8_t * sip = ( uint8_t * ) & sin . sin_addr . s_addr ;
2014-07-31 18:55:42 +00:00
DEBUG_LOG ( SCENET , " sceNetAdhocPdpRecv[%i:%u]: Received %u bytes from %u.%u.%u.%u:%u \n " , id , getLocalPort ( socket - > id ) , received , sip [ 0 ] , sip [ 1 ] , sip [ 2 ] , sip [ 3 ] , ntohs ( sin . sin_port ) ) ;
2014-06-24 16:43:03 +00:00
2013-11-28 06:05:11 +00:00
// Peer MAC
SceNetEtherAddr mac ;
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Find Peer MAC
2014-12-06 15:01:34 +00:00
if ( resolveIP ( sin . sin_addr . s_addr , & mac ) ) {
2013-11-28 06:05:11 +00:00
// Provide Sender Information
* saddr = mac ;
2014-06-26 10:50:37 +00:00
* sport = ntohs ( sin . sin_port ) ;
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Save Length
* len = received ;
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Free Network Lock
//_freeNetworkLock();
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Return Success
2014-06-25 13:29:42 +00:00
return 0 ;
2013-11-28 06:05:11 +00:00
}
2014-07-31 18:55:42 +00:00
WARN_LOG ( SCENET , " sceNetAdhocPdpRecv[%i:%u]: Received %i bytes from Unknown Peer %u.%u.%u.%u:%u [%02X:%02X:%02X:%02X:%02X:%02X] " , id , getLocalPort ( socket - > id ) , received , sip [ 0 ] , sip [ 1 ] , sip [ 2 ] , sip [ 3 ] , ntohs ( sin . sin_port ) , mac . data [ 0 ] , mac . data [ 1 ] , mac . data [ 2 ] , mac . data [ 3 ] , mac . data [ 4 ] , mac . data [ 5 ] ) ;
2014-06-26 10:50:37 +00:00
// Free Network Lock
//_freeNetworkLock();
2014-06-24 16:43:03 +00:00
2014-06-26 10:50:37 +00:00
//Receiving data from unknown peer, ignore it ?
2014-07-31 18:55:42 +00:00
//return ERROR_NET_ADHOC_WOULD_BLOCK; //ERROR_NET_ADHOC_NO_DATA_AVAILABLE
2013-11-28 06:05:11 +00:00
}
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Free Network Lock
//_freeNetworkLock();
2013-10-26 14:47:52 +00:00
# ifdef PDP_DIRTY_MAGIC
2013-11-28 06:05:11 +00:00
// Restore Nonblocking Flag for Return Value
2013-12-05 19:43:30 +00:00
if ( wouldblock ) flag = 1 ;
2013-10-26 14:47:52 +00:00
# endif
2013-11-28 06:05:11 +00:00
// Nothing received
2014-06-26 10:50:37 +00:00
if ( flag ) return ERROR_NET_ADHOC_WOULD_BLOCK ;
return ERROR_NET_ADHOC_TIMEOUT ;
2013-11-28 06:05:11 +00:00
}
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Invalid Argument
return ERROR_NET_ADHOC_INVALID_ARG ;
}
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Invalid Socket ID
return ERROR_NET_ADHOC_INVALID_SOCKET_ID ;
}
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Library is uninitialized
return ERROR_NET_ADHOC_NOT_INITIALIZED ;
2013-09-06 22:55:42 +00:00
}
2014-07-31 18:55:42 +00:00
// Flags seems to be bitmasks of ADHOC_F_ALERT...
int sceNetAdhocSetSocketAlert ( int id , int flag ) {
ERROR_LOG ( SCENET , " UNIMPL sceNetAdhocSetSocketAlert(%d, %08x) " , id , flag ) ;
return 0 ; //Dummy Result
2013-09-06 22:55:42 +00:00
}
2014-07-31 18:55:42 +00:00
int sceNetAdhocPollSocket ( u32 socketStructAddr , int count , int timeout , int nonblock ) { // timeout in microseconds
DEBUG_LOG ( SCENET , " UNTESTED sceNetAdhocPollSocket(%08x, %i, %i, %i) at %08x " , socketStructAddr , count , timeout , nonblock , currentMIPS - > pc ) ;
// Library is initialized
if ( netAdhocInited )
{
SceNetAdhocPollSd * sds = NULL ;
if ( Memory : : IsValidAddress ( socketStructAddr ) ) sds = ( SceNetAdhocPollSd * ) Memory : : GetPointer ( socketStructAddr ) ;
// Valid Arguments
if ( sds ! = NULL & & count > 0 )
{
// Socket Check
int i = 0 ; for ( ; i < count ; i + + )
{
// Invalid Socket
if ( sds [ i ] . id < 1 | | sds [ i ] . id > 255 | | ( pdp [ sds [ i ] . id - 1 ] = = NULL & & ptp [ sds [ i ] . id - 1 ] = = NULL ) ) return ERROR_NET_ADHOC_INVALID_SOCKET_ID ;
}
// Nonblocking Mode
if ( nonblock ) timeout = 0 ;
// Prevent Nonblocking Mode
else
if ( timeout = = 0 ) timeout = 1 ;
int affectedsockets = 0 ;
if ( count > FD_SETSIZE ) count = FD_SETSIZE ; // return affectedsockets;
// Acquire Network Lock
//acquireNetworkLock();
// Poll Sockets
//int affectedsockets = sceNetInetPoll(isds, count, timeout);
//WSAPoll only available for Vista or newer, so we'll use an alternative way for XP since Windows doesn't have poll function like *NIX
fd_set readfds , writefds , exceptfds ;
int fd ;
FD_ZERO ( & readfds ) ; FD_ZERO ( & writefds ) ; FD_ZERO ( & exceptfds ) ;
2014-08-11 16:25:24 +00:00
// TODO: PDP and PTP should share the same indexing to prevent identical PDP & PTP socket id
2014-07-31 18:55:42 +00:00
for ( int i = 0 ; i < count ; i + + ) {
sds [ i ] . revents = 0 ;
// Fill in Socket ID
2014-08-11 16:25:24 +00:00
if ( ptp [ sds [ i ] . id - 1 ] ! = NULL ) {
2014-07-31 18:55:42 +00:00
fd = ptp [ sds [ i ] . id - 1 ] - > id ;
if ( ptp [ sds [ i ] . id - 1 ] - > state = = ADHOC_PTP_STATE_LISTEN ) sds [ i ] . revents | = ADHOC_EV_ACCEPT ;
else
if ( ptp [ sds [ i ] . id - 1 ] - > state = = ADHOC_PTP_STATE_CLOSED ) sds [ i ] . revents | = ADHOC_EV_CONNECT ;
}
2014-08-11 16:25:24 +00:00
else {
fd = pdp [ sds [ i ] . id - 1 ] - > id ;
}
2014-07-31 18:55:42 +00:00
if ( sds [ i ] . events & ADHOC_EV_RECV ) FD_SET ( fd , & readfds ) ;
2014-08-11 16:25:24 +00:00
if ( sds [ i ] . events & ADHOC_EV_SEND ) FD_SET ( fd , & writefds ) ;
2014-07-31 18:55:42 +00:00
//if (sds[i].events & ADHOC_EV_ALERT)
FD_SET ( fd , & exceptfds ) ;
}
timeval tmout ;
tmout . tv_sec = timeout / 1000000 ; // seconds
tmout . tv_usec = ( timeout % 1000000 ) ; // microseconds
affectedsockets = select ( count , & readfds , & writefds , & exceptfds , & tmout ) ;
if ( affectedsockets > 0 ) {
affectedsockets = 0 ;
for ( int i = 0 ; i < count ; i + + ) {
2014-08-11 16:25:24 +00:00
if ( ptp [ sds [ i ] . id - 1 ] ! = NULL ) {
fd = ptp [ sds [ i ] . id - 1 ] - > id ;
2014-07-31 18:55:42 +00:00
}
else {
2014-08-11 16:25:24 +00:00
fd = pdp [ sds [ i ] . id - 1 ] - > id ;
2014-07-31 18:55:42 +00:00
}
if ( FD_ISSET ( fd , & readfds ) ) sds [ i ] . revents | = ADHOC_EV_RECV ;
2014-08-11 16:25:24 +00:00
if ( FD_ISSET ( fd , & writefds ) ) sds [ i ] . revents | = ADHOC_EV_SEND ; // Data can always be sent ?
2014-07-31 18:55:42 +00:00
sds [ i ] . revents & = sds [ i ] . events ;
if ( FD_ISSET ( fd , & exceptfds ) ) sds [ i ] . revents | = ADHOC_EV_ALERT ; // can be raised on revents regardless of events bitmask?
if ( sds [ i ] . revents ) affectedsockets + + ;
}
}
// Free Network Lock
//freeNetworkLock();
// Blocking Mode (Nonblocking Mode returns 0, even on Success)
if ( ! nonblock )
{
// Success
if ( affectedsockets > = 0 ) return affectedsockets ; // (affectedsockets > 0)
// Timeout
return ERROR_NET_ADHOC_TIMEOUT ;
}
// No Events generated
2014-08-11 16:25:24 +00:00
if ( affectedsockets > = 0 ) return 0 ;
return ERROR_NET_ADHOC_WOULD_BLOCK ; // Bleach 7 seems to use nonblocking and check the return value against 0 and 0x80410709 (also 0x80410717 ?)
2014-07-31 18:55:42 +00:00
}
// Invalid Argument
return ERROR_NET_ADHOC_INVALID_ARG ;
}
// Library is uninitialized
return ERROR_NET_ADHOC_NOT_INITIALIZED ;
2013-09-06 23:53:51 +00:00
}
2013-10-26 14:47:52 +00:00
/**
* Adhoc Emulator PDP Socket Delete
* @ param id Socket File Descriptor
* @ param flag Bitflags ( Unused )
* @ return 0 on success or . . . ADHOC_INVALID_ARG , ADHOC_NOT_INITIALIZED , ADHOC_INVALID_SOCKET_ID
*/
2014-12-08 09:40:08 +00:00
static int sceNetAdhocPdpDelete ( int id , int unknown ) {
2014-06-24 16:43:03 +00:00
// WLAN might be disabled in the middle of successfull multiplayer, but we still need to cleanup right?
INFO_LOG ( SCENET , " sceNetAdhocPdpDelete(%d, %d) at %08x " , id , unknown , currentMIPS - > pc ) ;
/*
2013-12-04 10:07:00 +00:00
if ( ! g_Config . bEnableWlan ) {
return 0 ;
}
2014-06-24 16:43:03 +00:00
*/
2013-11-28 06:05:11 +00:00
// Library is initialized
2013-12-05 19:43:30 +00:00
if ( netAdhocInited ) {
2013-11-28 06:05:11 +00:00
// Valid Arguments
2013-12-05 19:43:30 +00:00
if ( id > 0 & & id < = 255 ) {
2013-11-28 06:05:11 +00:00
// Cast Socket
SceNetAdhocPdpStat * sock = pdp [ id - 1 ] ;
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Valid Socket
2013-12-27 17:02:53 +00:00
if ( sock ! = NULL ) {
2013-11-28 06:05:11 +00:00
// Close Connection
closesocket ( sock - > id ) ;
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Remove Port Forward from Router
2013-12-27 17:02:53 +00:00
//sceNetPortClose("UDP", sock->lport);
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Free Memory
2013-12-27 17:02:53 +00:00
// free(sock);
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Free Translation Slot
pdp [ id - 1 ] = NULL ;
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Success
return 0 ;
}
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Invalid Socket ID
return ERROR_NET_ADHOC_INVALID_SOCKET_ID ;
}
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Invalid Argument
return ERROR_NET_ADHOC_INVALID_ARG ;
}
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Library is uninitialized
return ERROR_NET_ADHOC_NOT_INITIALIZED ;
2013-09-06 22:55:42 +00:00
}
2014-12-08 09:40:08 +00:00
static int sceNetAdhocctlGetAdhocId ( u32 productStructAddr ) {
2014-07-31 18:55:42 +00:00
ERROR_LOG ( SCENET , " UNIMPL sceNetAdhocctlGetAdhocId(%08x) " , productStructAddr ) ;
// Library initialized
if ( netAdhocctlInited )
{
// Valid Arguments
if ( Memory : : IsValidAddress ( productStructAddr ) )
{
SceNetAdhocctlAdhocId * adhoc_id = ( SceNetAdhocctlAdhocId * ) Memory : : GetPointer ( productStructAddr ) ;
// Copy Product ID
* adhoc_id = product_code ;
//Memory::WriteStruct(productStructAddr, &product_code);
// Return Success
return 0 ;
}
// Invalid Arguments
return ERROR_NET_ADHOCCTL_INVALID_ARG ;
}
// Library uninitialized
return ERROR_NET_ADHOCCTL_NOT_INITIALIZED ;
2013-09-06 22:55:42 +00:00
}
2014-12-08 09:40:08 +00:00
static int sceNetAdhocctlScan ( ) {
2014-06-24 16:43:03 +00:00
INFO_LOG ( SCENET , " sceNetAdhocctlScan() at %08x " , currentMIPS - > pc ) ;
2013-09-06 22:55:42 +00:00
2013-11-28 06:05:11 +00:00
// Library initialized
2013-12-05 19:43:30 +00:00
if ( netAdhocctlInited ) {
2013-11-28 06:05:11 +00:00
// Not connected
2013-12-05 19:43:30 +00:00
if ( threadStatus = = ADHOCCTL_STATE_DISCONNECTED ) {
2013-11-28 06:05:11 +00:00
threadStatus = ADHOCCTL_STATE_SCANNING ;
2013-10-26 22:08:21 +00:00
2013-11-28 06:05:11 +00:00
// Prepare Scan Request Packet
uint8_t opcode = OPCODE_SCAN ;
2013-10-28 20:30:25 +00:00
2014-06-24 16:43:03 +00:00
// Send Scan Request Packet, 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 , ( char * ) & opcode , 1 , 0 ) ;
if ( iResult = = SOCKET_ERROR ) {
2014-07-31 18:55:42 +00:00
int error = errno ;
ERROR_LOG ( SCENET , " Socket error (%i) when sending " , error ) ;
2014-06-24 16:43:03 +00:00
threadStatus = ADHOCCTL_STATE_DISCONNECTED ;
2014-07-31 18:55:42 +00:00
//if (error == ECONNABORTED || error == ECONNRESET || error == ENOTCONN) return ERROR_NET_ADHOCCTL_NOT_INITIALIZED; // A case where it need to reconnect to AdhocServer
2014-06-24 16:43:03 +00:00
return ERROR_NET_ADHOCCTL_DISCONNECTED ; // ERROR_NET_ADHOCCTL_BUSY
}
// Wait for Status to be connected to prevent Ford Street Racing from Failed to find game session
if ( friendFinderRunning ) {
int cnt = 0 ;
while ( ( threadStatus = = ADHOCCTL_STATE_SCANNING ) & & ( cnt < 5000 ) ) {
sleep_ms ( 1 ) ;
cnt + + ;
}
}
2013-10-28 20:30:25 +00:00
2013-11-28 06:05:11 +00:00
// Return Success
return 0 ;
}
2013-10-28 20:30:25 +00:00
2013-11-28 06:05:11 +00:00
// Library is busy
2014-06-24 16:43:03 +00:00
return ERROR_NET_ADHOCCTL_BUSY ; // ERROR_NET_ADHOCCTL_BUSY may trigger the game (ie. Ford Street Racing) to call sceNetAdhocctlDisconnect
2013-11-28 06:05:11 +00:00
}
2013-10-28 20:30:25 +00:00
2013-11-28 06:05:11 +00:00
// Library uninitialized
return ERROR_NET_ADHOCCTL_NOT_INITIALIZED ;
2013-10-26 22:08:21 +00:00
}
2014-07-31 18:55:42 +00:00
static int sceNetAdhocctlGetScanInfo ( u32 sizeAddr , u32 bufAddr ) {
s32_le * buflen = NULL ;
if ( Memory : : IsValidAddress ( sizeAddr ) ) buflen = ( s32_le * ) Memory : : GetPointer ( sizeAddr ) ;
SceNetAdhocctlScanInfoEmu * buf = NULL ;
if ( Memory : : IsValidAddress ( bufAddr ) ) buf = ( SceNetAdhocctlScanInfoEmu * ) Memory : : GetPointer ( bufAddr ) ;
INFO_LOG ( SCENET , " sceNetAdhocctlGetScanInfo([%08x]=%i, %08x) " , sizeAddr , buflen ? * buflen : - 1 , bufAddr ) ;
2013-12-04 10:07:00 +00:00
if ( ! g_Config . bEnableWlan ) {
return 0 ;
}
2014-07-31 18:55:42 +00:00
2013-11-28 06:05:11 +00:00
// Library initialized
2013-12-05 19:43:30 +00:00
if ( netAdhocctlInited ) {
2014-07-31 18:55:42 +00:00
// Minimum Argument
if ( buflen = = NULL ) return ERROR_NET_ADHOCCTL_INVALID_ARG ;
2014-06-24 16:43:03 +00:00
2013-11-28 06:05:11 +00:00
// Minimum Argument Requirements
2013-12-05 19:43:30 +00:00
if ( buflen ! = NULL ) {
2013-11-28 06:05:11 +00:00
// Multithreading Lock
peerlock . lock ( ) ;
2013-10-28 20:30:25 +00:00
2013-11-28 06:05:11 +00:00
// Length Returner Mode
2014-06-24 16:43:03 +00:00
if ( buf = = NULL ) * buflen = countAvailableNetworks ( ) * sizeof ( SceNetAdhocctlScanInfoEmu ) ;
2013-10-28 20:30:25 +00:00
2013-11-28 06:05:11 +00:00
// Normal Information Mode
else {
// Clear Memory
memset ( buf , 0 , * buflen ) ;
2013-10-28 20:30:25 +00:00
2013-11-28 06:05:11 +00:00
// Network Discovery Counter
int discovered = 0 ;
2013-10-28 20:30:25 +00:00
2013-11-28 06:05:11 +00:00
// Count requested Networks
2014-06-24 16:43:03 +00:00
int requestcount = * buflen / sizeof ( SceNetAdhocctlScanInfoEmu ) ;
2013-10-28 20:30:25 +00:00
2013-11-28 06:05:11 +00:00
// Minimum Argument Requirements
2013-12-05 19:43:30 +00:00
if ( requestcount > 0 ) {
2013-11-28 06:05:11 +00:00
// Group List Element
SceNetAdhocctlScanInfo * group = networks ;
2013-10-28 20:30:25 +00:00
2013-11-28 06:05:11 +00:00
// Iterate Group List
2013-12-05 19:43:30 +00:00
for ( ; group ! = NULL & & discovered < requestcount ; group = group - > next ) {
2013-11-28 06:05:11 +00:00
// Copy Group Information
2014-06-24 16:43:03 +00:00
//buf[discovered] = *group;
buf [ discovered ] . group_name = group - > group_name ;
buf [ discovered ] . bssid = group - > bssid ;
buf [ discovered ] . mode = group - > mode ;
2013-10-28 20:30:25 +00:00
2013-11-28 06:05:11 +00:00
// Exchange Adhoc Channel
// sceUtilityGetSystemParamInt(PSP_SYSTEMPARAM_ID_INT_ADHOC_CHANNEL, &buf[discovered].channel);
2013-10-28 20:30:25 +00:00
2013-11-28 06:05:11 +00:00
// Fake Channel Number 1 on Automatic Channel
2013-12-05 19:43:30 +00:00
// if (buf[discovered].channel == 0) buf[discovered].channel = 1;
2013-10-26 22:08:21 +00:00
2013-11-28 06:05:11 +00:00
//Always Fake Channel 1
buf [ discovered ] . channel = 1 ;
2013-10-28 20:30:25 +00:00
2013-11-28 06:05:11 +00:00
// Increase Discovery Counter
discovered + + ;
}
2013-10-28 20:30:25 +00:00
2013-11-28 06:05:11 +00:00
// Link List
2013-12-05 19:43:30 +00:00
int i = 0 ; for ( ; i < discovered - 1 ; i + + ) {
2013-11-28 06:05:11 +00:00
// Link Network
2014-06-24 16:43:03 +00:00
buf [ i ] . next = bufAddr + ( sizeof ( SceNetAdhocctlScanInfoEmu ) * i ) + sizeof ( SceNetAdhocctlScanInfoEmu ) ; // buf[i].next = &buf[i + 1];
2013-11-28 06:05:11 +00:00
}
2013-10-28 20:30:25 +00:00
2013-11-28 06:05:11 +00:00
// Fix Last Element
2014-06-24 16:43:03 +00:00
if ( discovered > 0 ) buf [ discovered - 1 ] . next = 0 ;
2013-11-28 06:05:11 +00:00
}
2013-10-28 20:30:25 +00:00
2013-11-28 06:05:11 +00:00
// Fix Size
2014-06-24 16:43:03 +00:00
* buflen = discovered * sizeof ( SceNetAdhocctlScanInfoEmu ) ;
2013-11-28 06:05:11 +00:00
}
2013-10-28 20:30:25 +00:00
2013-11-28 06:05:11 +00:00
// Multithreading Unlock
peerlock . unlock ( ) ;
2013-10-28 20:30:25 +00:00
2013-11-28 06:05:11 +00:00
// Return Success
return 0 ;
}
2013-10-28 20:30:25 +00:00
2013-11-28 06:05:11 +00:00
// Generic Error
return - 1 ;
}
2013-10-28 20:30:25 +00:00
2013-11-28 06:05:11 +00:00
// Library uninitialized
return ERROR_NET_ADHOCCTL_NOT_INITIALIZED ;
2013-09-06 22:55:42 +00:00
}
// TODO: How many handlers can the PSP actually have for Adhocctl?
// TODO: Should we allow the same handler to be added more than once?
2014-12-08 09:40:08 +00:00
static u32 sceNetAdhocctlAddHandler ( u32 handlerPtr , u32 handlerArg ) {
2013-11-28 06:05:11 +00:00
bool foundHandler = false ;
u32 retval = 0 ;
struct AdhocctlHandler handler ;
memset ( & handler , 0 , sizeof ( handler ) ) ;
2013-09-06 22:55:42 +00:00
2013-11-28 06:05:11 +00:00
while ( adhocctlHandlers . find ( retval ) ! = adhocctlHandlers . end ( ) )
+ + retval ;
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
handler . entryPoint = handlerPtr ;
handler . argument = handlerArg ;
2013-09-06 23:53:51 +00:00
2014-12-25 03:20:21 +00:00
for ( auto it = adhocctlHandlers . begin ( ) ; it ! = adhocctlHandlers . end ( ) ; + + it ) {
2013-11-28 06:05:11 +00:00
if ( it - > second . entryPoint = = handlerPtr ) {
foundHandler = true ;
break ;
}
}
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
if ( ! foundHandler & & Memory : : IsValidAddress ( handlerPtr ) ) {
if ( adhocctlHandlers . size ( ) > = MAX_ADHOCCTL_HANDLERS ) {
2014-01-12 20:33:29 +00:00
ERROR_LOG ( SCENET , " UNTESTED sceNetAdhocctlAddHandler(%x, %x): Too many handlers " , handlerPtr , handlerArg ) ;
2013-11-28 06:05:11 +00:00
retval = ERROR_NET_ADHOCCTL_TOO_MANY_HANDLERS ;
return retval ;
}
adhocctlHandlers [ retval ] = handler ;
WARN_LOG ( SCENET , " UNTESTED sceNetAdhocctlAddHandler(%x, %x): added handler %d " , handlerPtr , handlerArg , retval ) ;
2014-06-24 16:43:03 +00:00
} else if ( foundHandler ) {
2013-11-28 06:05:11 +00:00
ERROR_LOG ( SCENET , " UNTESTED sceNetAdhocctlAddHandler(%x, %x): Same handler already exists " , handlerPtr , handlerArg ) ;
2014-06-24 16:43:03 +00:00
retval = 0 ; //Faking success
} else {
ERROR_LOG ( SCENET , " UNTESTED sceNetAdhocctlAddHandler(%x, %x): Invalid handler " , handlerPtr , handlerArg ) ;
retval = ERROR_NET_ADHOCCTL_INVALID_ARG ;
2013-11-28 06:05:11 +00:00
}
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// The id to return is the number of handlers currently registered
return retval ;
2013-09-06 23:53:51 +00:00
}
2014-12-08 09:40:08 +00:00
static u32 sceNetAdhocctlDisconnect ( ) {
2014-06-24 16:43:03 +00:00
// WLAN might be disabled in the middle of successfull multiplayer, but we still need to cleanup right?
2014-07-31 18:55:42 +00:00
INFO_LOG ( SCENET , " sceNetAdhocctlDisconnect() at %08x [group=%s] " , currentMIPS - > pc , parameter . group_name . data ) ;
2014-06-24 16:43:03 +00:00
/*
2013-12-04 10:07:00 +00:00
if ( ! g_Config . bEnableWlan ) {
return 0 ;
}
2014-06-24 16:43:03 +00:00
*/
2013-11-28 06:05:11 +00:00
// Library initialized
2013-12-05 19:43:30 +00:00
if ( netAdhocctlInited ) {
2013-11-28 06:05:11 +00:00
// Connected State (Adhoc Mode)
2014-06-24 16:43:03 +00:00
if ( threadStatus ! = ADHOCCTL_STATE_DISCONNECTED ) { // (threadStatus == ADHOCCTL_STATE_CONNECTED)
2013-11-28 06:05:11 +00:00
// Clear Network Name
memset ( & parameter . group_name , 0 , sizeof ( parameter . group_name ) ) ;
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Set Disconnected State
threadStatus = ADHOCCTL_STATE_DISCONNECTED ;
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Set HUD Connection Status
//setConnectionStatus(0);
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Prepare Packet
uint8_t opcode = OPCODE_DISCONNECT ;
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Acquire Network Lock
//_acquireNetworkLock();
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Send Disconnect Request Packet
2014-06-24 16:43:03 +00:00
int iResult = send ( metasocket , ( const char * ) & opcode , 1 , 0 ) ;
if ( iResult = = SOCKET_ERROR ) {
ERROR_LOG ( SCENET , " Socket error (%i) when sending " , errno ) ;
}
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Free Network Lock
//_freeNetworkLock();
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Multithreading Lock
2014-07-31 18:55:42 +00:00
//peerlock.lock();
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Clear Peer List
2014-07-31 18:55:42 +00:00
//freeFriendsRecursive(friends);
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Delete Peer Reference
2014-07-31 18:55:42 +00:00
//friends = NULL;
2013-10-26 14:47:52 +00:00
2014-06-24 16:43:03 +00:00
// Clear Group List
2014-07-31 18:55:42 +00:00
//freeGroupsRecursive(networks);
2014-06-24 16:43:03 +00:00
// Delete Group Reference
2014-07-31 18:55:42 +00:00
//networks = NULL;
2014-06-24 16:43:03 +00:00
2013-11-28 06:05:11 +00:00
// Multithreading Unlock
2014-07-31 18:55:42 +00:00
//peerlock.unlock();
2013-11-28 06:05:11 +00:00
}
2014-06-24 16:43:03 +00:00
2013-11-28 06:05:11 +00:00
// Notify Event Handlers (even if we weren't connected, not doing this will freeze games like God Eater, which expect this behaviour)
2015-01-04 13:07:44 +00:00
{
lock_guard adhocGuard ( adhocEvtMtx ) ;
adhocctlEvents . push_back ( { ADHOCCTL_EVENT_DISCONNECT , 0 } ) ;
}
2014-06-24 16:43:03 +00:00
// Return Success, some games might ignore returned value and always treat it as success, otherwise repeatedly calling this function
2013-11-28 06:05:11 +00:00
return 0 ;
}
2013-09-06 22:55:42 +00:00
2013-11-28 06:05:11 +00:00
// Library uninitialized
2014-06-24 16:43:03 +00:00
return 0 ; //ERROR_NET_ADHOC_NOT_INITIALIZED; // Wipeout Pulse will repeatedly calling this function if returned value is ERROR_NET_ADHOC_NOT_INITIALIZED
2013-09-06 22:55:42 +00:00
}
2014-12-08 09:40:08 +00:00
static u32 sceNetAdhocctlDelHandler ( u32 handlerID ) {
2013-11-28 06:05:11 +00:00
if ( adhocctlHandlers . find ( handlerID ) ! = adhocctlHandlers . end ( ) ) {
adhocctlHandlers . erase ( handlerID ) ;
WARN_LOG ( SCENET , " UNTESTED sceNetAdhocctlDelHandler(%d): deleted handler %d " , handlerID , handlerID ) ;
} else {
ERROR_LOG ( SCENET , " UNTESTED sceNetAdhocctlDelHandler(%d): asked to delete invalid handler %d " , handlerID , handlerID ) ;
}
2013-09-06 22:55:42 +00:00
2013-11-28 06:05:11 +00:00
return 0 ;
2013-09-06 22:55:42 +00:00
}
int sceNetAdhocctlTerm ( ) {
2014-06-24 16:43:03 +00:00
// WLAN might be disabled in the middle of successfull multiplayer, but we still need to cleanup right?
INFO_LOG ( SCENET , " sceNetAdhocctlTerm() " ) ;
2014-07-31 18:55:42 +00:00
if ( netAdhocMatchingInited ) sceNetAdhocMatchingTerm ( ) ;
2013-12-04 10:07:00 +00:00
2013-12-05 19:43:30 +00:00
if ( netAdhocctlInited ) {
2013-11-28 06:05:11 +00:00
netAdhocctlInited = false ;
friendFinderRunning = false ;
2013-12-05 19:43:30 +00:00
if ( friendFinderThread . joinable ( ) ) {
2013-11-28 06:05:11 +00:00
friendFinderThread . join ( ) ;
}
2014-06-24 16:43:03 +00:00
//May also need to clear Handlers
adhocctlHandlers . clear ( ) ;
2013-12-05 19:43:30 +00:00
// Free stuff here
2013-11-28 06:05:11 +00:00
closesocket ( metasocket ) ;
2013-11-28 06:30:48 +00:00
metasocket = ( int ) INVALID_SOCKET ;
2014-07-31 18:55:42 +00:00
/*#ifdef _MSC_VER
WSACleanup ( ) ; // Might be better to call WSAStartup/WSACleanup from sceNetInit/sceNetTerm isn't? since it's the first/last network function being used, even better to put it in __NetInit/__NetShutdown as it's only called once
# endif* /
2013-11-28 06:05:11 +00:00
}
2013-09-06 22:55:42 +00:00
2013-11-28 06:05:11 +00:00
return 0 ;
2013-09-06 22:55:42 +00:00
}
2014-12-08 09:40:08 +00:00
static int sceNetAdhocctlGetNameByAddr ( const char * mac , u32 nameAddr ) {
2014-07-31 18:55:42 +00:00
DEBUG_LOG ( SCENET , " UNTESTED sceNetAdhocctlGetNameByAddr(%s, %08x) " , mac , nameAddr ) ;
// Library initialized
if ( netAdhocctlInited )
{
// Valid Arguments
2015-01-04 13:09:41 +00:00
if ( mac ! = NULL & & nameAddr ! = 0 )
2014-07-31 18:55:42 +00:00
{
SceNetAdhocctlNickname * nickname = NULL ;
if ( Memory : : IsValidAddress ( nameAddr ) ) nickname = ( SceNetAdhocctlNickname * ) Memory : : GetPointer ( nameAddr ) ;
// Get Local MAC Address
SceNetEtherAddr localmac ; getLocalMac ( & localmac ) ;
// Local MAC Matches
if ( memcmp ( & localmac , mac , sizeof ( SceNetEtherAddr ) ) = = 0 )
{
// Write Data
* nickname = parameter . nickname ;
// Return Success
return 0 ;
}
// Multithreading Lock
peerlock . lock ( ) ;
// Peer Reference
SceNetAdhocctlPeerInfo * peer = friends ;
// Iterate Peers
for ( ; peer ! = NULL ; peer = peer - > next )
{
// Match found
if ( memcmp ( & peer - > mac_addr , mac , sizeof ( SceNetEtherAddr ) ) = = 0 )
{
// Write Data
* nickname = peer - > nickname ;
// Multithreading Unlock
peerlock . unlock ( ) ;
// Return Success
return 0 ;
}
}
// Multithreading Unlock
peerlock . unlock ( ) ;
// Player not found
return ERROR_NET_ADHOC_NO_ENTRY ;
}
// Invalid Arguments
return ERROR_NET_ADHOCCTL_INVALID_ARG ;
}
// Library uninitialized
return ERROR_NET_ADHOCCTL_NOT_INITIALIZED ;
2013-09-07 09:06:06 +00:00
}
2013-09-06 22:55:42 +00:00
2014-12-08 09:40:08 +00:00
static int sceNetAdhocctlJoin ( u32 scanInfoAddr ) {
2014-06-24 16:43:03 +00:00
WARN_LOG ( SCENET , " UNTESTED sceNetAdhocctlJoin(%08x) at %08x " , scanInfoAddr , currentMIPS - > pc ) ;
if ( ! g_Config . bEnableWlan ) {
return - 1 ;
}
// Library initialized
2014-07-31 18:55:42 +00:00
if ( netAdhocctlInited )
{
// Valid Argument
if ( Memory : : IsValidAddress ( scanInfoAddr ) )
{
SceNetAdhocctlScanInfoEmu * sinfo = ( SceNetAdhocctlScanInfoEmu * ) Memory : : GetPointer ( scanInfoAddr ) ;
//while (true) sleep_ms(1);
2014-06-24 16:43:03 +00:00
2014-07-31 18:55:42 +00:00
// We can ignore minor connection process differences here
return sceNetAdhocctlCreate ( ( const char * ) & sinfo - > group_name ) ;
}
2014-06-24 16:43:03 +00:00
2014-07-31 18:55:42 +00:00
// Invalid Argument
return ERROR_NET_ADHOCCTL_INVALID_ARG ;
}
2014-06-24 16:43:03 +00:00
2014-07-31 18:55:42 +00:00
// Uninitialized Library
return ERROR_NET_ADHOCCTL_NOT_INITIALIZED ;
}
2014-06-24 16:43:03 +00:00
2014-07-31 18:55:42 +00:00
int sceNetAdhocctlGetPeerInfo ( const char * mac , int size , u32 peerInfoAddr ) {
VERBOSE_LOG ( SCENET , " sceNetAdhocctlGetPeerInfo(%s, %i, %08x) at %08x " , mac , size , peerInfoAddr , currentMIPS - > pc ) ;
if ( ! g_Config . bEnableWlan ) {
return - 1 ;
}
2014-06-24 16:43:03 +00:00
2014-07-31 18:55:42 +00:00
SceNetEtherAddr * maddr = ( SceNetEtherAddr * ) mac ;
SceNetAdhocctlPeerInfoEmu * buf = NULL ;
if ( Memory : : IsValidAddress ( peerInfoAddr ) ) {
buf = ( SceNetAdhocctlPeerInfoEmu * ) Memory : : GetPointer ( peerInfoAddr ) ;
}
// Library initialized
if ( netAdhocctlInited ) {
2015-01-04 13:09:41 +00:00
if ( ( size < ( int ) sizeof ( SceNetAdhocctlPeerInfoEmu ) ) | | ( buf = = NULL ) ) return ERROR_NET_ADHOCCTL_INVALID_ARG ;
2014-07-31 18:55:42 +00:00
int retval = ERROR_NET_ADHOCCTL_INVALID_ARG ; // -1;
// Local MAC
if ( isLocalMAC ( maddr ) ) {
sockaddr_in addr ;
SceNetAdhocctlNickname nickname ;
getLocalIp ( & addr ) ;
strcpy ( ( char * ) nickname . data , g_Config . sNickName . c_str ( ) ) ;
//buf->next = 0;
buf - > nickname = nickname ;
buf - > nickname . data [ ADHOCCTL_NICKNAME_LEN - 1 ] = 0 ; // last char need to be null-terminated char
buf - > mac_addr = * maddr ;
buf - > ip_addr = addr . sin_addr . s_addr ; // 0x11111111;
//buf->padding = 0x1111; //0;
buf - > last_recv = CoreTiming : : GetGlobalTimeUsScaled ( ) ;
2014-06-24 16:43:03 +00:00
2014-07-31 18:55:42 +00:00
// Success
retval = 0 ;
}
// Find Peer by MAC
else
{
// Multithreading Lock
peerlock . lock ( ) ;
2014-06-24 16:43:03 +00:00
2014-07-31 18:55:42 +00:00
SceNetAdhocctlPeerInfo * peer = findFriend ( maddr ) ;
if ( peer ! = NULL ) {
// Fake Receive Time
if ( peer - > last_recv ! = 0 ) peer - > last_recv = CoreTiming : : GetGlobalTimeUsScaled ( ) ;
2014-06-24 16:43:03 +00:00
2014-07-31 18:55:42 +00:00
//buf->next = 0;
buf - > nickname = peer - > nickname ;
buf - > nickname . data [ ADHOCCTL_NICKNAME_LEN - 1 ] = 0 ; // last char need to be null-terminated char
buf - > mac_addr = * maddr ;
buf - > ip_addr = peer - > ip_addr ; // 0x11111111;
//buf->padding = /*0;*/ 0x1111;
buf - > last_recv = peer - > last_recv ; //CoreTiming::GetGlobalTimeUsScaled(); //real_time_now()*1000000.0; //(uint64_t)time(NULL); //This timestamp is important issue on Dissidia 012
2014-06-24 16:43:03 +00:00
2014-07-31 18:55:42 +00:00
// Success
retval = 0 ;
2014-06-24 16:43:03 +00:00
}
2014-07-31 18:55:42 +00:00
// Multithreading Unlock
peerlock . unlock ( ) ;
2014-06-24 16:43:03 +00:00
}
2014-07-31 18:55:42 +00:00
return retval ;
2014-06-24 16:43:03 +00:00
}
2014-07-31 18:55:42 +00:00
// Library uninitialized
2014-06-24 16:43:03 +00:00
return ERROR_NET_ADHOCCTL_NOT_INITIALIZED ;
2013-09-06 22:55:42 +00:00
}
2013-10-26 14:47:52 +00:00
/**
* Create and / or Join a Virtual Network of the specified Name
* @ param group_name Virtual Network Name
* @ return 0 on success or . . . ADHOCCTL_NOT_INITIALIZED , ADHOCCTL_INVALID_ARG , ADHOCCTL_BUSY
*/
2013-09-07 09:06:06 +00:00
int sceNetAdhocctlCreate ( const char * groupName ) {
2014-06-24 16:43:03 +00:00
INFO_LOG ( SCENET , " sceNetAdhocctlCreate(%s) at %08x " , groupName , currentMIPS - > pc ) ;
2013-12-04 10:07:00 +00:00
if ( ! g_Config . bEnableWlan ) {
return - 1 ;
}
2013-11-28 06:05:11 +00:00
const SceNetAdhocctlGroupName * groupNameStruct = ( const SceNetAdhocctlGroupName * ) groupName ;
// Library initialized
2013-12-05 19:43:30 +00:00
if ( netAdhocctlInited ) {
2013-11-28 06:05:11 +00:00
// Valid Argument
2013-12-05 19:43:30 +00:00
if ( validNetworkName ( groupNameStruct ) ) {
2014-06-24 16:43:03 +00:00
// Disconnected State, may also need to check for Scanning state to prevent some games from failing to host a game session
if ( ( threadStatus = = ADHOCCTL_STATE_DISCONNECTED ) | | ( threadStatus = = ADHOCCTL_STATE_SCANNING ) ) {
2013-11-28 06:05:11 +00:00
// Set Network Name
2013-12-05 19:43:30 +00:00
if ( groupNameStruct ! = NULL ) parameter . group_name = * groupNameStruct ;
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Reset Network Name
else memset ( & parameter . group_name , 0 , sizeof ( parameter . group_name ) ) ;
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Prepare Connect Packet
SceNetAdhocctlConnectPacketC2S packet ;
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Clear Packet Memory
memset ( & packet , 0 , sizeof ( packet ) ) ;
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Set Packet Opcode
packet . base . opcode = OPCODE_CONNECT ;
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Set Target Group
2013-12-05 19:43:30 +00:00
if ( groupNameStruct ! = NULL ) packet . group = * groupNameStruct ;
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Acquire Network Lock
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Send Packet
2014-06-24 16:43:03 +00:00
int iResult = send ( metasocket , ( const char * ) & packet , sizeof ( packet ) , 0 ) ;
if ( iResult = = SOCKET_ERROR ) {
ERROR_LOG ( SCENET , " Socket error (%i) when sending " , errno ) ;
2014-07-31 18:55:42 +00:00
//return ERROR_NET_ADHOCCTL_NOT_INITIALIZED; // ERROR_NET_ADHOCCTL_DISCONNECTED; // ERROR_NET_ADHOCCTL_BUSY;
//Faking success, to prevent Full Auto 2 from freezing while Initializing Network
threadStatus = ADHOCCTL_STATE_CONNECTED ;
// Notify Event Handlers, Needed for the Nickname to be shown on the screen when success is faked
// Might be better not to notify the game when faking success (failed to connect to adhoc server), at least the player will know that it failed to connect
//__UpdateAdhocctlHandlers(ADHOCCTL_EVENT_CONNECT, 0); //CoreTiming::ScheduleEvent_Threadsafe_Immediate(eventAdhocctlHandlerUpdate, join32(ADHOCCTL_EVENT_CONNECT, 0));
2014-06-24 16:43:03 +00:00
}
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Free Network Lock
2013-10-26 14:47:52 +00:00
2013-11-28 06:05:11 +00:00
// Set HUD Connection Status
//setConnectionStatus(1);
2013-10-26 14:47:52 +00:00
2014-06-24 16:43:03 +00:00
// Wait for Status to be connected to prevent Ford Street Racing from Failed to create game session
if ( friendFinderRunning ) {
int cnt = 0 ;
while ( ( threadStatus ! = ADHOCCTL_STATE_CONNECTED ) & & ( cnt < 5000 ) ) {
sleep_ms ( 1 ) ;
cnt + + ;
}
}
2013-11-28 06:05:11 +00:00
// Return Success
return 0 ;
}
2014-06-24 16:43:03 +00:00
2013-11-28 06:05:11 +00:00
// Connected State
2014-06-24 16:43:03 +00:00
return ERROR_NET_ADHOCCTL_BUSY ; // ERROR_NET_ADHOCCTL_BUSY may trigger the game (ie. Ford Street Racing) to call sceNetAdhocctlDisconnect
2013-11-28 06:05:11 +00:00
}
2014-06-24 16:43:03 +00:00
2013-11-28 06:05:11 +00:00
// Invalid Argument
return ERROR_NET_ADHOC_INVALID_ARG ;
}
// Library uninitialized
return ERROR_NET_ADHOCCTL_NOT_INITIALIZED ;
2013-10-26 14:47:52 +00:00
}
2014-12-08 09:40:08 +00:00
static int sceNetAdhocctlConnect ( u32 ptrToGroupName ) {
2013-11-28 06:05:11 +00:00
if ( Memory : : IsValidAddress ( ptrToGroupName ) ) {
2014-06-24 16:43:03 +00:00
INFO_LOG ( SCENET , " sceNetAdhocctlConnect(groupName=%s) at %08x " , Memory : : GetCharPointer ( ptrToGroupName ) , currentMIPS - > pc ) ;
2013-11-28 06:05:11 +00:00
return sceNetAdhocctlCreate ( Memory : : GetCharPointer ( ptrToGroupName ) ) ;
2014-07-31 18:55:42 +00:00
}
return ERROR_NET_ADHOC_INVALID_ARG ; // ERROR_NET_ADHOC_INVALID_ADDR;
2013-09-06 22:55:42 +00:00
}
2014-12-08 09:40:08 +00:00
static int sceNetAdhocctlCreateEnterGameMode ( const char * groupName , int unknown , int playerNum , u32 macsAddr , int timeout , int unknown2 ) {
2014-06-24 16:43:03 +00:00
ERROR_LOG ( SCENET , " UNIMPL sceNetAdhocctlCreateEnterGameMode(%s, %i, %i, %08x, %i, %i) at %08x " , groupName , unknown , playerNum , macsAddr , timeout , unknown2 , currentMIPS - > pc ) ;
2013-11-28 06:05:11 +00:00
return - 1 ;
2013-09-07 09:06:06 +00:00
}
2014-12-08 09:40:08 +00:00
static int sceNetAdhocctlJoinEnterGameMode ( const char * groupName , const char * macAddr , int timeout , int unknown2 ) {
2014-06-24 16:43:03 +00:00
ERROR_LOG ( SCENET , " UNIMPL sceNetAdhocctlJoinEnterGameMode(%s, %s, %i, %i) at %08x " , groupName , macAddr , timeout , unknown2 , currentMIPS - > pc ) ;
2013-11-28 06:05:11 +00:00
return - 1 ;
2013-09-07 09:06:06 +00:00
}
2014-07-31 18:55:42 +00:00
/**
* Create and Join a GameMode Network as Host ( with Minimum Peer Check )
* @ param group_name Virtual Network Name
* @ param game_type Network Type ( 1 A , 1 B , 2 A )
* @ param min_members Minimum Number of Peers
* @ param num_members Total Number of Peers ( including Host )
* @ param members MAC Address List of Peers ( own MAC at Index 0 )
* @ param timeout Timeout Value ( in Microseconds )
* @ param flag Unused Bitflags
* @ return 0 on success or . . . ADHOCCTL_NOT_INITIALIZED , ADHOCCTL_INVALID_ARG , ADHOCCTL_BUSY , ADHOCCTL_CHANNEL_NOT_AVAILABLE
*/
int sceNetAdhocctlCreateEnterGameModeMin ( const char * group_name , int game_type , int min_members , int num_members , u32 membersAddr , u32 timeout , int flag )
{
ERROR_LOG ( SCENET , " UNIMPL sceNetAdhocctlCreateEnterGameModeMin(%s, %i, %i, %i, %08x, %d, %i) at %08x " , group_name , game_type , min_members , num_members , membersAddr , timeout , flag , currentMIPS - > pc ) ;
// We don't really need the Minimum User Check
return sceNetAdhocctlCreateEnterGameMode ( group_name , game_type , num_members , membersAddr , timeout , flag ) ;
}
2013-09-07 09:06:06 +00:00
int sceNetAdhocTerm ( ) {
2014-06-24 16:43:03 +00:00
INFO_LOG ( SCENET , " sceNetAdhocTerm() " ) ;
// WLAN might be disabled in the middle of successfull multiplayer, but we still need to cleanup all the sockets right?
2014-07-31 18:55:42 +00:00
if ( netAdhocctlInited ) sceNetAdhocctlTerm ( ) ;
2013-12-04 10:07:00 +00:00
2013-11-28 06:05:11 +00:00
// Library is initialized
2013-12-05 19:43:30 +00:00
if ( netAdhocInited ) {
2014-07-31 18:55:42 +00:00
// Delete fake PSP Thread
if ( threadAdhocID ! = 0 ) {
__KernelStopThread ( threadAdhocID , SCE_KERNEL_ERROR_THREAD_TERMINATED , " AdhocThread stopped " ) ;
__KernelDeleteThread ( threadAdhocID , SCE_KERNEL_ERROR_THREAD_TERMINATED , " AdhocThread deleted " ) ;
}
2013-11-28 06:05:11 +00:00
// Delete PDP Sockets
deleteAllPDP ( ) ;
// Delete PTP Sockets
deleteAllPTP ( ) ;
// Delete Gamemode Buffer
2014-07-31 18:55:42 +00:00
//deleteAllGMB();
2013-11-28 06:05:11 +00:00
// Terminate Internet Library
//sceNetInetTerm();
// Unload Internet Modules (Just keep it in memory... unloading crashes?!)
2013-12-05 19:43:30 +00:00
// if (_manage_modules != 0) sceUtilityUnloadModule(PSP_MODULE_NET_INET);
2013-11-28 06:05:11 +00:00
// Library shutdown
netAdhocInited = false ;
return 0 ;
} else {
// Seems to return this when called a second time after being terminated without another initialisation
return SCE_KERNEL_ERROR_LWMUTEX_NOT_FOUND ;
}
2013-09-06 22:55:42 +00:00
}
2014-07-31 18:55:42 +00:00
static int sceNetAdhocGetPdpStat ( u32 structSize , u32 structAddr ) {
VERBOSE_LOG ( SCENET , " UNTESTED sceNetAdhocGetPdpStat(%08x, %08x) at %08x " , structSize , structAddr , currentMIPS - > pc ) ;
// Library is initialized
if ( netAdhocInited )
{
s32_le * buflen = NULL ;
if ( Memory : : IsValidAddress ( structSize ) ) buflen = ( s32_le * ) Memory : : GetPointer ( structSize ) ;
SceNetAdhocPdpStat * buf = NULL ;
if ( Memory : : IsValidAddress ( structAddr ) ) buf = ( SceNetAdhocPdpStat * ) Memory : : GetPointer ( structAddr ) ;
// Length Returner Mode
if ( buflen ! = NULL & & buf = = NULL )
{
// Return Required Size
* buflen = sizeof ( SceNetAdhocPdpStat ) * getPDPSocketCount ( ) ;
// Success
return 0 ;
}
// Status Returner Mode
else if ( buflen ! = NULL & & buf ! = NULL )
{
// Socket Count
int socketcount = getPDPSocketCount ( ) ;
// Figure out how many Sockets we will return
int count = * buflen / sizeof ( SceNetAdhocPdpStat ) ;
if ( count > socketcount ) count = socketcount ;
// Copy Counter
int i = 0 ;
// Iterate Translation Table
int j = 0 ; for ( ; j < 255 & & i < count ; j + + )
{
// Valid Socket Entry
if ( pdp [ j ] ! = NULL )
{
// Copy Socket Data from Internal Memory
buf [ i ] = * pdp [ j ] ;
// Fix Client View Socket ID
buf [ i ] . id = j + 1 ;
// Write End of List Reference
buf [ i ] . next = 0 ;
// Link Previous Element
if ( i > 0 )
buf [ i - 1 ] . next = structAddr + ( ( i - 1 ) * sizeof ( SceNetAdhocPdpStat ) ) + sizeof ( SceNetAdhocPdpStat ) ; //buf[i - 1].next = &buf[i];
// Increment Counter
i + + ;
}
}
// Update Buffer Length
* buflen = i * sizeof ( SceNetAdhocPdpStat ) ;
// Success
return 0 ;
}
// Invalid Arguments
return ERROR_NET_ADHOC_INVALID_ARG ;
}
// Library is uninitialized
return ERROR_NET_ADHOC_NOT_INITIALIZED ;
}
2013-10-29 21:06:26 +00:00
/**
* Adhoc Emulator PTP Socket List Getter
* @ param buflen IN : Length of Buffer in Bytes OUT : Required Length of Buffer in Bytes
* @ param buf PTP Socket List Buffer ( can be NULL if you wish to receive Required Length )
* @ return 0 on success or . . . ADHOC_INVALID_ARG , ADHOC_NOT_INITIALIZED
*/
2014-12-08 09:40:08 +00:00
static int sceNetAdhocGetPtpStat ( u32 structSize , u32 structAddr ) {
2013-11-28 06:05:11 +00:00
// Spams a lot
2014-07-31 18:55:42 +00:00
VERBOSE_LOG ( SCENET , " sceNetAdhocGetPtpStat(%08x, %08x) at %08x " , structSize , structAddr , currentMIPS - > pc ) ;
2013-12-04 10:07:00 +00:00
2014-07-31 18:55:42 +00:00
s32_le * buflen = NULL ;
if ( Memory : : IsValidAddress ( structSize ) ) buflen = ( s32_le * ) Memory : : GetPointer ( structSize ) ;
SceNetAdhocPtpStat * buf = NULL ;
if ( Memory : : IsValidAddress ( structAddr ) ) buf = ( SceNetAdhocPtpStat * ) Memory : : GetPointer ( structAddr ) ;
2013-12-04 10:07:00 +00:00
2013-10-29 21:06:26 +00:00
// Library is initialized
2013-12-05 19:43:30 +00:00
if ( netAdhocInited ) {
2013-10-29 21:06:26 +00:00
// Length Returner Mode
2014-07-31 18:55:42 +00:00
if ( buflen ! = NULL & & buf = = NULL ) {
2013-10-29 21:06:26 +00:00
// Return Required Size
2013-11-10 01:26:31 +00:00
* buflen = sizeof ( SceNetAdhocPtpStat ) * getPTPSocketCount ( ) ;
2013-10-29 21:06:26 +00:00
// Success
return 0 ;
}
// Status Returner Mode
2014-07-31 18:55:42 +00:00
else if ( buflen ! = NULL & & buf ! = NULL ) {
2013-10-29 21:06:26 +00:00
// Socket Count
2013-11-10 01:26:31 +00:00
int socketcount = getPTPSocketCount ( ) ;
2013-10-29 21:06:26 +00:00
// Figure out how many Sockets we will return
int count = * buflen / sizeof ( SceNetAdhocPtpStat ) ;
2013-12-05 19:43:30 +00:00
if ( count > socketcount ) count = socketcount ;
2013-10-29 21:06:26 +00:00
// Copy Counter
int i = 0 ;
// Iterate Sockets
2013-12-05 19:43:30 +00:00
int j = 0 ; for ( ; j < 255 & & i < count ; j + + ) {
2013-10-29 21:06:26 +00:00
// Active Socket
2013-12-05 19:43:30 +00:00
if ( ptp [ j ] ! = NULL ) {
2013-10-29 21:06:26 +00:00
// Copy Socket Data from internal Memory
buf [ i ] = * ptp [ j ] ;
// Fix Client View Socket ID
buf [ i ] . id = j + 1 ;
// Write End of List Reference
buf [ i ] . next = 0 ;
// Link previous Element to this one
2013-12-05 19:43:30 +00:00
if ( i > 0 )
2014-07-31 18:55:42 +00:00
buf [ i - 1 ] . next = structAddr + ( ( i - 1 ) * sizeof ( SceNetAdhocPtpStat ) ) + sizeof ( SceNetAdhocPtpStat ) ;
2013-10-29 21:06:26 +00:00
// Increment Counter
i + + ;
}
}
// Update Buffer Length
* buflen = i * sizeof ( SceNetAdhocPtpStat ) ;
// Success
return 0 ;
}
// Invalid Arguments
return ERROR_NET_ADHOC_INVALID_ARG ;
}
// Library is uninitialized
return ERROR_NET_ADHOC_NOT_INITIALIZED ;
2013-09-06 23:53:51 +00:00
}
2013-10-29 21:06:26 +00:00
/**
* Adhoc Emulator PTP Active Socket Creator
* @ param saddr Local MAC ( Unused )
* @ param sport Local Binding Port
* @ param daddr Target MAC
* @ param dport Target Port
* @ param bufsize Socket Buffer Size
* @ param rexmt_int Retransmit Interval ( in Microseconds )
* @ param rexmt_cnt Retransmit Count
* @ param flag Bitflags ( Unused )
* @ return Socket ID > 0 on success or . . . ADHOC_NOT_INITIALIZED , ADHOC_INVALID_ARG , ADHOC_INVALID_ADDR , ADHOC_INVALID_PORT
*/
2014-12-08 09:40:08 +00:00
static int sceNetAdhocPtpOpen ( const char * srcmac , int sport , const char * dstmac , int dport , int bufsize , int rexmt_int , int rexmt_cnt , int unknown ) {
2014-07-31 18:55:42 +00:00
INFO_LOG ( SCENET , " sceNetAdhocPtpOpen(%s,%d,%s,%d,%d,%d,%d,%d) " , srcmac , sport , dstmac , dport , bufsize , rexmt_int , rexmt_cnt , unknown ) ;
2013-12-04 10:07:00 +00:00
if ( ! g_Config . bEnableWlan ) {
return 0 ;
}
2013-11-28 06:05:11 +00:00
SceNetEtherAddr * saddr = ( SceNetEtherAddr * ) srcmac ;
SceNetEtherAddr * daddr = ( SceNetEtherAddr * ) dstmac ;
2013-10-29 21:06:26 +00:00
// Library is initialized
2013-12-05 19:43:30 +00:00
if ( netAdhocInited ) {
2013-10-29 21:06:26 +00:00
// Valid Addresses
2013-12-05 19:43:30 +00:00
if ( saddr ! = NULL & & isLocalMAC ( saddr ) & & daddr ! = NULL & & ! isBroadcastMAC ( daddr ) ) {
2013-10-29 21:06:26 +00:00
// Random Port required
2013-12-05 19:43:30 +00:00
if ( sport = = 0 ) {
2013-10-29 21:06:26 +00:00
// Find unused Port
2013-12-05 19:43:30 +00:00
// while (sport == 0 || _IsPTPPortInUse(sport)) {
2013-10-29 21:06:26 +00:00
// // Generate Port Number
// sport = (uint16_t)_getRandomNumber(65535);
// }
}
// Valid Ports
2013-12-05 19:43:30 +00:00
if ( ! isPTPPortInUse ( sport ) & & dport ! = 0 ) {
2013-10-29 21:06:26 +00:00
// Valid Arguments
2013-12-05 19:43:30 +00:00
if ( bufsize > 0 & & rexmt_int > 0 & & rexmt_cnt > 0 ) {
2013-10-29 21:06:26 +00:00
// Create Infrastructure Socket
2014-09-07 11:27:26 +00:00
int tcpsocket = ( int ) INVALID_SOCKET ;
tcpsocket = socket ( AF_INET , SOCK_STREAM , IPPROTO_TCP ) ;
2013-10-29 21:06:26 +00:00
// Valid Socket produced
2013-12-05 19:43:30 +00:00
if ( tcpsocket > 0 ) {
2014-07-31 18:55:42 +00:00
// Change socket buffer size when necessary
if ( getSockBufferSize ( tcpsocket , SO_SNDBUF ) < bufsize ) setSockBufferSize ( tcpsocket , SO_SNDBUF , bufsize ) ;
if ( getSockBufferSize ( tcpsocket , SO_RCVBUF ) < bufsize ) setSockBufferSize ( tcpsocket , SO_RCVBUF , bufsize ) ;
2013-10-29 21:06:26 +00:00
// Enable Port Re-use
2013-11-25 01:57:08 +00:00
setsockopt ( tcpsocket , SOL_SOCKET , SO_REUSEADDR , ( const char * ) & one , sizeof ( one ) ) ;
2013-10-29 21:06:26 +00:00
// Binding Information for local Port
sockaddr_in addr ;
// addr.sin_len = sizeof(addr);
addr . sin_family = AF_INET ;
addr . sin_addr . s_addr = INADDR_ANY ;
addr . sin_port = htons ( sport ) ;
// Bound Socket to local Port
2013-12-05 19:43:30 +00:00
if ( bind ( tcpsocket , ( sockaddr * ) & addr , sizeof ( addr ) ) = = 0 ) {
2014-01-04 14:57:08 +00:00
// Update sport with the port assigned by bind
socklen_t len = sizeof ( addr ) ;
if ( getsockname ( tcpsocket , ( sockaddr * ) & addr , & len ) = = 0 ) {
sport = ntohs ( addr . sin_port ) ;
}
2013-10-29 21:06:26 +00:00
// Allocate Memory
SceNetAdhocPtpStat * internal = ( SceNetAdhocPtpStat * ) malloc ( sizeof ( SceNetAdhocPtpStat ) ) ;
// Allocated Memory
2013-12-05 19:43:30 +00:00
if ( internal ! = NULL ) {
2013-10-29 21:06:26 +00:00
// Find Free Translator ID
2013-12-05 19:43:30 +00:00
int i = 0 ; for ( ; i < 255 ; i + + ) if ( ptp [ i ] = = NULL ) break ;
2013-10-29 21:06:26 +00:00
// Found Free Translator ID
2013-12-05 19:43:30 +00:00
if ( i < 255 ) {
2013-10-29 21:06:26 +00:00
// Clear Memory
memset ( internal , 0 , sizeof ( SceNetAdhocPtpStat ) ) ;
// Copy Infrastructure Socket ID
internal - > id = tcpsocket ;
// Copy Address Information
internal - > laddr = * saddr ;
internal - > paddr = * daddr ;
internal - > lport = sport ;
internal - > pport = dport ;
// Set Buffer Size
internal - > rcv_sb_cc = bufsize ;
// Link PTP Socket
ptp [ i ] = internal ;
// Add Port Forward to Router
// sceNetPortOpen("TCP", sport);
// Return PTP Socket Pointer
return i + 1 ;
}
// Free Memory
free ( internal ) ;
}
}
// Close Socket
closesocket ( tcpsocket ) ;
}
}
// Invalid Arguments
return ERROR_NET_ADHOC_INVALID_ARG ;
}
// Invalid Ports
return ERROR_NET_ADHOC_INVALID_PORT ;
}
// Invalid Addresses
return ERROR_NET_ADHOC_INVALID_ADDR ;
}
2013-11-28 06:05:11 +00:00
return 0 ;
2013-09-06 23:53:51 +00:00
}
2013-10-29 21:06:26 +00:00
/**
* Adhoc Emulator PTP Connection Acceptor
* @ param id Socket File Descriptor
* @ param addr OUT : Peer MAC Address
* @ param port OUT : Peer Port
* @ param timeout Accept Timeout ( in Microseconds )
* @ param flag Nonblocking Flag
* @ return Socket ID > = 0 on success or . . . ADHOC_NOT_INITIALIZED , ADHOC_INVALID_ARG , ADHOC_INVALID_SOCKET_ID , ADHOC_SOCKET_DELETED , ADHOC_SOCKET_ALERTED , ADHOC_SOCKET_ID_NOT_AVAIL , ADHOC_WOULD_BLOCK , ADHOC_TIMEOUT , ADHOC_NOT_LISTENED , ADHOC_THREAD_ABORTED , NET_INTERNAL
*/
2014-12-08 09:40:08 +00:00
static int sceNetAdhocPtpAccept ( int id , u32 peerMacAddrPtr , u32 peerPortPtr , int timeout , int flag ) {
2013-12-04 10:07:00 +00:00
2013-11-28 06:05:11 +00:00
SceNetEtherAddr * addr = NULL ;
2013-12-05 19:43:30 +00:00
if ( Memory : : IsValidAddress ( peerMacAddrPtr ) ) {
2014-02-27 08:28:57 +00:00
addr = PSPPointer < SceNetEtherAddr > : : Create ( peerMacAddrPtr ) ;
2013-11-28 06:05:11 +00:00
}
2014-06-24 16:43:03 +00:00
uint16_t * port = NULL ; //
2013-12-05 19:43:30 +00:00
if ( Memory : : IsValidAddress ( peerPortPtr ) ) {
2013-12-04 10:07:00 +00:00
port = ( uint16_t * ) Memory : : GetPointer ( peerPortPtr ) ;
2013-11-28 06:05:11 +00:00
}
2014-07-31 18:55:42 +00:00
DEBUG_LOG ( SCENET , " sceNetAdhocPtpAccept(%d,%08x,[%08x]=%u,%d,%u) at %08x " , id , peerMacAddrPtr , peerPortPtr , port ? * port : - 1 , timeout , flag , currentMIPS - > pc ) ;
2013-12-04 10:07:00 +00:00
if ( ! g_Config . bEnableWlan ) {
return 0 ;
}
2013-10-29 21:06:26 +00:00
// Library is initialized
2013-12-05 19:43:30 +00:00
if ( netAdhocInited ) {
2013-10-29 21:06:26 +00:00
// Valid Socket
2013-12-05 19:43:30 +00:00
if ( id > 0 & & id < = 255 & & ptp [ id - 1 ] ! = NULL ) {
2013-10-29 21:06:26 +00:00
// Cast Socket
SceNetAdhocPtpStat * socket = ptp [ id - 1 ] ;
// Listener Socket
2014-07-31 18:55:42 +00:00
if ( socket - > state = = ADHOC_PTP_STATE_LISTEN ) {
2013-10-29 21:06:26 +00:00
// Valid Arguments
2014-07-31 18:55:42 +00:00
if ( addr ! = NULL /*&& port != NULL*/ ) { //GTA:VCS seems to use 0 for the portPtr
2013-10-29 21:06:26 +00:00
// Address Information
sockaddr_in peeraddr ;
memset ( & peeraddr , 0 , sizeof ( peeraddr ) ) ;
2013-11-28 06:15:39 +00:00
socklen_t peeraddrlen = sizeof ( peeraddr ) ;
2013-10-29 21:06:26 +00:00
// Local Address Information
sockaddr_in local ;
memset ( & local , 0 , sizeof ( local ) ) ;
2013-11-28 06:15:39 +00:00
socklen_t locallen = sizeof ( local ) ;
2013-10-29 21:06:26 +00:00
// Grab Nonblocking Flag
2013-11-25 01:57:08 +00:00
uint32_t nbio = getBlockingFlag ( socket - > id ) ;
2013-10-29 21:06:26 +00:00
// Switch to Nonblocking Behaviour
2013-12-05 19:43:30 +00:00
if ( nbio = = 0 ) {
2013-10-29 21:06:26 +00:00
// Overwrite Socket Option
2013-11-28 06:05:11 +00:00
changeBlockingMode ( socket - > id , 1 ) ;
2013-10-29 21:06:26 +00:00
}
// Accept Connection
int newsocket = accept ( socket - > id , ( sockaddr * ) & peeraddr , & peeraddrlen ) ;
// Blocking Behaviour
2013-12-05 19:43:30 +00:00
if ( ! flag & & newsocket = = - 1 ) {
2013-10-29 21:06:26 +00:00
// Get Start Time
2014-07-31 18:55:42 +00:00
uint32_t starttime = ( uint32_t ) ( real_time_now ( ) * 1000000.0 ) ;
2013-10-29 21:06:26 +00:00
// Retry until Timeout hits
2014-07-31 18:55:42 +00:00
while ( ( timeout = = 0 | | ( ( uint32_t ) ( real_time_now ( ) * 1000000.0 ) - starttime ) < ( uint32_t ) timeout ) & & newsocket = = - 1 ) {
2013-10-29 21:06:26 +00:00
// Accept Connection
newsocket = accept ( socket - > id , ( sockaddr * ) & peeraddr , & peeraddrlen ) ;
// Wait a bit...
2013-10-30 14:45:32 +00:00
sleep_ms ( 1 ) ;
2013-10-29 21:06:26 +00:00
}
}
2014-07-31 18:55:42 +00:00
if ( newsocket = = SOCKET_ERROR ) {
int error = errno ;
DEBUG_LOG ( SCENET , " sceNetAdhocPtpAccept[%i]: Socket Error (%i) " , id , error ) ;
}
2013-10-29 21:06:26 +00:00
// Restore Blocking Behaviour
2013-12-05 19:43:30 +00:00
if ( nbio = = 0 ) {
2013-10-29 21:06:26 +00:00
// Restore Socket Option
2013-11-28 06:05:11 +00:00
changeBlockingMode ( socket - > id , 0 ) ;
2013-10-29 21:06:26 +00:00
}
// Accepted New Connection
2013-12-05 19:43:30 +00:00
if ( newsocket > 0 ) {
2014-07-31 18:55:42 +00:00
// Do we need to Change socket buffer size to match the listener buffer size?
2013-10-29 21:06:26 +00:00
// Enable Port Re-use
2013-11-25 01:57:08 +00:00
setsockopt ( newsocket , SOL_SOCKET , SO_REUSEADDR , ( const char * ) & one , sizeof ( one ) ) ;
2013-10-29 21:06:26 +00:00
// Grab Local Address
2013-12-05 19:43:30 +00:00
if ( getsockname ( newsocket , ( sockaddr * ) & local , & locallen ) = = 0 ) {
2013-10-29 21:06:26 +00:00
// Peer MAC
SceNetEtherAddr mac ;
// Find Peer MAC
2014-12-06 15:01:34 +00:00
if ( resolveIP ( peeraddr . sin_addr . s_addr , & mac ) ) {
2013-10-29 21:06:26 +00:00
// Allocate Memory
SceNetAdhocPtpStat * internal = ( SceNetAdhocPtpStat * ) malloc ( sizeof ( SceNetAdhocPtpStat ) ) ;
// Allocated Memory
2013-12-05 19:43:30 +00:00
if ( internal ! = NULL ) {
2013-10-29 21:06:26 +00:00
// Find Free Translator ID
2013-12-05 19:43:30 +00:00
int i = 0 ; for ( ; i < 255 ; i + + ) if ( ptp [ i ] = = NULL ) break ;
2013-10-29 21:06:26 +00:00
// Found Free Translator ID
2013-12-05 19:43:30 +00:00
if ( i < 255 ) {
2013-10-29 21:06:26 +00:00
// Clear Memory
memset ( internal , 0 , sizeof ( SceNetAdhocPtpStat ) ) ;
// Copy Socket Descriptor to Structure
internal - > id = newsocket ;
2014-07-31 18:55:42 +00:00
// Set Buffer Size
if ( getSockBufferSize ( newsocket , SO_RCVBUF ) < socket - > rcv_sb_cc ) setSockBufferSize ( newsocket , SO_RCVBUF , socket - > rcv_sb_cc ) ;
if ( getSockBufferSize ( newsocket , SO_SNDBUF ) < socket - > snd_sb_cc ) setSockBufferSize ( newsocket , SO_SNDBUF , socket - > snd_sb_cc ) ;
internal - > rcv_sb_cc = socket - > rcv_sb_cc ;
internal - > snd_sb_cc = socket - > snd_sb_cc ;
2013-10-29 21:06:26 +00:00
// Copy Local Address Data to Structure
2013-11-10 01:26:31 +00:00
getLocalMac ( & internal - > laddr ) ;
2014-06-26 10:50:37 +00:00
internal - > lport = ntohs ( local . sin_port ) ;
2013-10-29 21:06:26 +00:00
// Copy Peer Address Data to Structure
internal - > paddr = mac ;
2014-06-26 10:50:37 +00:00
internal - > pport = ntohs ( peeraddr . sin_port ) ;
2013-10-29 21:06:26 +00:00
// Set Connected State
2014-07-31 18:55:42 +00:00
internal - > state = ADHOC_PTP_STATE_ESTABLISHED ;
2013-10-29 21:06:26 +00:00
// Return Peer Address Information
* addr = internal - > paddr ;
2014-07-31 18:55:42 +00:00
if ( port ! = NULL ) * port = internal - > pport ;
2013-10-29 21:06:26 +00:00
// Link PTP Socket
ptp [ i ] = internal ;
// Add Port Forward to Router
// sceNetPortOpen("TCP", internal->lport);
2014-07-31 18:55:42 +00:00
uint8_t * pip = ( uint8_t * ) & peeraddr . sin_addr . s_addr ;
INFO_LOG ( SCENET , " sceNetAdhocPtpAccept[%i->%i:%u]: Established (%u.%u.%u.%u:%u) " , id , i + 1 , internal - > lport , pip [ 0 ] , pip [ 1 ] , pip [ 2 ] , pip [ 3 ] , internal - > pport ) ;
2013-10-29 21:06:26 +00:00
// Return Socket
return i + 1 ;
}
// Free Memory
free ( internal ) ;
}
}
}
// Close Socket
closesocket ( newsocket ) ;
2014-07-31 18:55:42 +00:00
ERROR_LOG ( SCENET , " sceNetAdhocPtpAccept[%i]: Failed (Socket Closed) " , id ) ;
2013-10-29 21:06:26 +00:00
}
// Action would block
2013-12-05 19:43:30 +00:00
if ( flag ) return ERROR_NET_ADHOC_WOULD_BLOCK ;
2013-10-29 21:06:26 +00:00
// Timeout
return ERROR_NET_ADHOC_TIMEOUT ;
}
// Invalid Arguments
return ERROR_NET_ADHOC_INVALID_ARG ;
}
// Client Socket
return ERROR_NET_ADHOC_NOT_LISTENED ;
}
// Invalid Socket
return ERROR_NET_ADHOC_INVALID_SOCKET_ID ;
}
// Library is uninitialized
return ERROR_NET_ADHOC_NOT_INITIALIZED ;
2013-09-06 23:53:51 +00:00
}
2013-10-29 21:06:26 +00:00
/**
* Adhoc Emulator PTP Connection Opener
* @ param id Socket File Descriptor
* @ param timeout Connect Timeout ( in Microseconds )
* @ param flag Nonblocking Flag
* @ return 0 on success or . . . ADHOC_NOT_INITIALIZED , ADHOC_INVALID_ARG , ADHOC_INVALID_SOCKET_ID , ADHOC_SOCKET_DELETED , ADHOC_CONNECTION_REFUSED , ADHOC_SOCKET_ALERTED , ADHOC_WOULD_BLOCK , ADHOC_TIMEOUT , ADHOC_NOT_OPENED , ADHOC_THREAD_ABORTED , NET_INTERNAL
*/
2014-12-08 09:40:08 +00:00
static int sceNetAdhocPtpConnect ( int id , int timeout , int flag ) {
2014-07-31 18:55:42 +00:00
INFO_LOG ( SCENET , " sceNetAdhocPtpConnect(%i, %i, %08x) at %08x " , id , timeout , flag , currentMIPS - > pc ) ;
2013-12-04 10:07:00 +00:00
if ( ! g_Config . bEnableWlan ) {
return 0 ;
}
2013-10-29 21:06:26 +00:00
// Library is initialized
2013-12-05 19:43:30 +00:00
if ( netAdhocInited )
2013-10-29 21:06:26 +00:00
{
// Valid Socket
2013-12-05 19:43:30 +00:00
if ( id > 0 & & id < = 255 & & ptp [ id - 1 ] ! = NULL ) {
2013-10-29 21:06:26 +00:00
// Cast Socket
SceNetAdhocPtpStat * socket = ptp [ id - 1 ] ;
// Valid Client Socket
2013-12-05 19:43:30 +00:00
if ( socket - > state = = 0 ) {
2013-10-29 21:06:26 +00:00
// Target Address
sockaddr_in sin ;
memset ( & sin , 0 , sizeof ( sin ) ) ;
// Setup Target Address
// sin.sin_len = sizeof(sin);
sin . sin_family = AF_INET ;
sin . sin_port = htons ( socket - > pport ) ;
// Grab Peer IP
2014-12-06 15:01:34 +00:00
if ( resolveMAC ( & socket - > paddr , ( uint32_t * ) & sin . sin_addr . s_addr ) ) {
2013-10-29 21:06:26 +00:00
// Grab Nonblocking Flag
2013-11-25 01:57:08 +00:00
uint32_t nbio = getBlockingFlag ( socket - > id ) ;
2013-10-29 21:06:26 +00:00
// Switch to Nonblocking Behaviour
2013-12-05 19:43:30 +00:00
if ( nbio = = 0 ) {
2013-10-29 21:06:26 +00:00
// Overwrite Socket Option
2013-11-28 06:05:11 +00:00
changeBlockingMode ( socket - > id , 1 ) ;
2013-10-29 21:06:26 +00:00
}
// Connect Socket to Peer (Nonblocking)
int connectresult = connect ( socket - > id , ( sockaddr * ) & sin , sizeof ( sin ) ) ;
// Grab Error Code
int errorcode = errno ;
2014-07-31 18:55:42 +00:00
if ( connectresult = = SOCKET_ERROR ) {
ERROR_LOG ( SCENET , " sceNetAdhocPtpConnect[%i]: Socket Error (%i) " , id , errorcode ) ;
}
2013-10-29 21:06:26 +00:00
// Restore Blocking Behaviour
2013-12-05 19:43:30 +00:00
if ( nbio = = 0 ) {
2013-10-29 21:06:26 +00:00
// Restore Socket Option
2013-11-28 06:05:11 +00:00
changeBlockingMode ( socket - > id , 0 ) ;
2013-10-29 21:06:26 +00:00
}
// Instant Connection (Lucky!)
2014-07-31 18:55:42 +00:00
if ( connectresult = = 0 | | ( connectresult = = - 1 & & ( errorcode = = EISCONN /*|| errorcode == EALREADY)*/ ) ) ) {
2013-10-29 21:06:26 +00:00
// Set Connected State
2014-07-31 18:55:42 +00:00
socket - > state = ADHOC_PTP_STATE_ESTABLISHED ;
2013-10-29 21:06:26 +00:00
2014-08-11 16:25:24 +00:00
INFO_LOG ( SCENET , " sceNetAdhocPtpConnect[%i:%u]: Already Connected " , id , socket - > lport ) ;
2013-10-29 21:06:26 +00:00
// Success
return 0 ;
}
// Connection in Progress
2014-05-18 13:41:02 +00:00
else if ( connectresult = = - 1 & & connectInProgress ( errorcode ) ) {
2013-10-29 21:06:26 +00:00
// Nonblocking Mode
2013-12-05 19:43:30 +00:00
if ( flag ) return ERROR_NET_ADHOC_WOULD_BLOCK ;
2013-10-29 21:06:26 +00:00
// Blocking Mode
else {
// Grab Connection Start Time
2014-07-31 18:55:42 +00:00
uint32_t starttime = ( uint32_t ) ( real_time_now ( ) * 1000000.0 ) ;
2013-10-29 21:06:26 +00:00
// Peer Information (for Connection-Polling)
sockaddr_in peer ;
memset ( & peer , 0 , sizeof ( peer ) ) ;
2013-11-28 06:15:39 +00:00
socklen_t peerlen = sizeof ( peer ) ;
2013-10-29 21:06:26 +00:00
// Wait for Connection
2014-07-31 18:55:42 +00:00
while ( ( timeout = = 0 | | ( ( uint32_t ) ( real_time_now ( ) * 1000000.0 ) - starttime ) < ( uint32_t ) timeout ) & & getpeername ( socket - > id , ( sockaddr * ) & peer , & peerlen ) ! = 0 ) {
2013-10-29 21:06:26 +00:00
// Wait 1ms
2013-11-28 06:05:11 +00:00
sleep_ms ( 1 ) ;
2013-10-29 21:06:26 +00:00
}
// Connected in Time
2013-12-05 19:43:30 +00:00
if ( sin . sin_addr . s_addr = = peer . sin_addr . s_addr /* && sin.sin_port == peer.sin_port*/ ) {
2013-10-29 21:06:26 +00:00
// Set Connected State
2014-07-31 18:55:42 +00:00
socket - > state = ADHOC_PTP_STATE_ESTABLISHED ;
uint8_t * pip = ( uint8_t * ) & peer . sin_addr . s_addr ;
INFO_LOG ( SCENET , " sceNetAdhocPtpConnect[%i:%u]: Established (%u.%u.%u.%u:%u) " , id , socket - > lport , pip [ 0 ] , pip [ 1 ] , pip [ 2 ] , pip [ 3 ] , socket - > pport ) ;
2013-10-29 21:06:26 +00:00
// Success
return 0 ;
}
// Timeout occured
return ERROR_NET_ADHOC_TIMEOUT ;
}
}
}
// Peer not found
return ERROR_NET_ADHOC_CONNECTION_REFUSED ;
}
// Not a valid Client Socket
return ERROR_NET_ADHOC_NOT_OPENED ;
}
// Invalid Socket
return ERROR_NET_ADHOC_INVALID_SOCKET_ID ;
}
// Library is uninitialized
return ERROR_NET_ADHOC_NOT_INITIALIZED ;
2013-09-06 23:53:51 +00:00
}
2013-10-29 21:06:26 +00:00
/**
* Adhoc Emulator PTP Socket Closer
* @ param id Socket File Descriptor
* @ param flag Bitflags ( Unused )
* @ return 0 on success or . . . ADHOC_NOT_INITIALIZED , ADHOC_INVALID_ARG , ADHOC_INVALID_SOCKET_ID , ADHOC_SOCKET_DELETED
*/
2014-12-08 09:40:08 +00:00
static int sceNetAdhocPtpClose ( int id , int unknown ) {
2014-07-31 18:55:42 +00:00
INFO_LOG ( SCENET , " sceNetAdhocPtpClose(%d,%d) at %08x " , id , unknown , currentMIPS - > pc ) ;
2013-12-04 10:07:00 +00:00
if ( ! g_Config . bEnableWlan ) {
return 0 ;
}
2013-10-29 21:06:26 +00:00
// Library is initialized
2013-12-05 19:43:30 +00:00
if ( netAdhocInited ) {
2013-10-29 21:06:26 +00:00
// Valid Arguments & Atleast one Socket
2013-12-05 19:43:30 +00:00
if ( id > 0 & & id < = 255 & & ptp [ id - 1 ] ! = NULL ) {
2013-10-29 21:06:26 +00:00
// Cast Socket
SceNetAdhocPtpStat * socket = ptp [ id - 1 ] ;
// Close Connection
closesocket ( socket - > id ) ;
// Remove Port Forward from Router
// sceNetPortClose("TCP", socket->lport);
// Free Memory
free ( socket ) ;
// Free Reference
ptp [ id - 1 ] = NULL ;
// Success
return 0 ;
}
// Invalid Argument
return ERROR_NET_ADHOC_INVALID_SOCKET_ID ;
}
// Library is uninitialized
return ERROR_NET_ADHOC_NOT_INITIALIZED ;
2013-09-06 23:53:51 +00:00
}
2013-10-29 21:06:26 +00:00
/**
* Adhoc Emulator PTP Passive Socket Creator
* @ param saddr Local MAC ( Unused )
* @ param sport Local Binding Port
* @ param bufsize Socket Buffer Size
* @ param rexmt_int Retransmit Interval ( in Microseconds )
* @ param rexmt_cnt Retransmit Count
* @ param backlog Size of Connection Queue
* @ param flag Bitflags ( Unused )
* @ return Socket ID > 0 on success or . . . ADHOC_NOT_INITIALIZED , ADHOC_INVALID_ARG , ADHOC_INVALID_ADDR , ADHOC_INVALID_PORT , ADHOC_SOCKET_ID_NOT_AVAIL , ADHOC_PORT_NOT_AVAIL , ADHOC_PORT_IN_USE , NET_NO_SPACE
*/
2014-12-08 09:40:08 +00:00
static int sceNetAdhocPtpListen ( const char * srcmac , int sport , int bufsize , int rexmt_int , int rexmt_cnt , int backlog , int unk ) {
2014-07-31 18:55:42 +00:00
INFO_LOG ( SCENET , " sceNetAdhocPtpListen(%s,%d,%d,%d,%d,%d,%d) " , srcmac , sport , bufsize , rexmt_int , rexmt_cnt , backlog , unk ) ;
2013-12-04 10:07:00 +00:00
if ( ! g_Config . bEnableWlan ) {
return 0 ;
}
2013-10-29 21:06:26 +00:00
// Library is initialized
2013-11-28 06:05:11 +00:00
SceNetEtherAddr * saddr = ( SceNetEtherAddr * ) srcmac ;
2013-12-05 19:43:30 +00:00
if ( netAdhocInited ) {
2013-10-29 21:06:26 +00:00
// Valid Address
2013-12-05 19:43:30 +00:00
if ( saddr ! = NULL & & isLocalMAC ( saddr ) )
2013-10-29 21:06:26 +00:00
{
// Random Port required
2013-12-05 19:43:30 +00:00
if ( sport = = 0 ) {
2013-10-29 21:06:26 +00:00
// Find unused Port
2013-12-05 19:43:30 +00:00
// while (sport == 0 || __IsPTPPortInUse(sport))
2013-10-29 21:06:26 +00:00
// {
// // Generate Port Number
// sport = (uint16_t)_getRandomNumber(65535);
// }
}
// Valid Ports
2013-12-05 19:43:30 +00:00
if ( ! isPTPPortInUse ( sport ) ) {
2013-10-29 21:06:26 +00:00
// Valid Arguments
2013-12-05 19:43:30 +00:00
if ( bufsize > 0 & & rexmt_int > 0 & & rexmt_cnt > 0 & & backlog > 0 )
2013-10-29 21:06:26 +00:00
{
// Create Infrastructure Socket
int tcpsocket = socket ( AF_INET , SOCK_STREAM , IPPROTO_TCP ) ;
// Valid Socket produced
2013-12-05 19:43:30 +00:00
if ( tcpsocket > 0 ) {
2014-07-31 18:55:42 +00:00
// Change socket buffer size when necessary
if ( getSockBufferSize ( tcpsocket , SO_SNDBUF ) < bufsize ) setSockBufferSize ( tcpsocket , SO_SNDBUF , bufsize ) ;
if ( getSockBufferSize ( tcpsocket , SO_RCVBUF ) < bufsize ) setSockBufferSize ( tcpsocket , SO_RCVBUF , bufsize ) ;
2013-10-29 21:06:26 +00:00
// Enable Port Re-use
2013-11-25 01:57:08 +00:00
setsockopt ( tcpsocket , SOL_SOCKET , SO_REUSEADDR , ( const char * ) & one , sizeof ( one ) ) ;
2013-10-29 21:06:26 +00:00
// Binding Information for local Port
sockaddr_in addr ;
addr . sin_family = AF_INET ;
addr . sin_addr . s_addr = INADDR_ANY ;
addr . sin_port = htons ( sport ) ;
2014-07-31 18:55:42 +00:00
int iResult = 0 ;
2013-10-29 21:06:26 +00:00
// Bound Socket to local Port
2014-07-31 18:55:42 +00:00
if ( ( iResult = bind ( tcpsocket , ( sockaddr * ) & addr , sizeof ( addr ) ) ) = = 0 ) {
2013-10-29 21:06:26 +00:00
// Switch into Listening Mode
2014-07-31 18:55:42 +00:00
if ( ( iResult = listen ( tcpsocket , backlog ) ) = = 0 ) {
2013-10-29 21:06:26 +00:00
// Allocate Memory
SceNetAdhocPtpStat * internal = ( SceNetAdhocPtpStat * ) malloc ( sizeof ( SceNetAdhocPtpStat ) ) ;
// Allocated Memory
2013-12-05 19:43:30 +00:00
if ( internal ! = NULL ) {
2013-10-29 21:06:26 +00:00
// Find Free Translator ID
2013-12-05 19:43:30 +00:00
int i = 0 ; for ( ; i < 255 ; i + + ) if ( ptp [ i ] = = NULL ) break ;
2013-10-29 21:06:26 +00:00
// Found Free Translator ID
2013-12-05 19:43:30 +00:00
if ( i < 255 ) {
2013-10-29 21:06:26 +00:00
// Clear Memory
memset ( internal , 0 , sizeof ( SceNetAdhocPtpStat ) ) ;
// Copy Infrastructure Socket ID
internal - > id = tcpsocket ;
// Copy Address Information
internal - > laddr = * saddr ;
internal - > lport = sport ;
// Flag Socket as Listener
2014-07-31 18:55:42 +00:00
internal - > state = ADHOC_PTP_STATE_LISTEN ;
2013-10-29 21:06:26 +00:00
// Set Buffer Size
internal - > rcv_sb_cc = bufsize ;
// Link PTP Socket
ptp [ i ] = internal ;
// Add Port Forward to Router
// sceNetPortOpen("TCP", sport);
// Return PTP Socket Pointer
return i + 1 ;
}
// Free Memory
free ( internal ) ;
}
}
}
2014-07-31 18:55:42 +00:00
if ( iResult = = SOCKET_ERROR ) {
int error = errno ;
ERROR_LOG ( SCENET , " sceNetAdhocPtpListen[%i]: Socket Error (%i) " , sport , error ) ;
}
2013-10-29 21:06:26 +00:00
// Close Socket
closesocket ( tcpsocket ) ;
2014-07-31 18:55:42 +00:00
// Port not available (exclusively in use?)
return ERROR_NET_ADHOC_PORT_NOT_AVAIL ;
2013-10-29 21:06:26 +00:00
}
// Socket not available
return ERROR_NET_ADHOC_SOCKET_ID_NOT_AVAIL ;
}
// Invalid Arguments
return ERROR_NET_ADHOC_INVALID_ARG ;
}
// Invalid Ports
return ERROR_NET_ADHOC_PORT_IN_USE ;
}
// Invalid Addresses
return ERROR_NET_ADHOC_INVALID_ADDR ;
}
// Library is uninitialized
return ERROR_NET_ADHOC_NOT_INITIALIZED ;
2013-09-06 23:53:51 +00:00
}
2013-10-29 21:06:26 +00:00
/**
* Adhoc Emulator PTP Sender
* @ param id Socket File Descriptor
* @ param data Data Payload
* @ param len IN : Length of Payload OUT : Sent Data ( in Bytes )
* @ param timeout Send Timeout ( in Microseconds )
* @ param flag Nonblocking Flag
* @ return 0 on success or . . . ADHOC_NOT_INITIALIZED , ADHOC_INVALID_ARG , ADHOC_INVALID_SOCKET_ID , ADHOC_SOCKET_DELETED , ADHOC_SOCKET_ALERTED , ADHOC_WOULD_BLOCK , ADHOC_TIMEOUT , ADHOC_NOT_CONNECTED , ADHOC_THREAD_ABORTED , ADHOC_INVALID_DATALEN , ADHOC_DISCONNECTED , NET_INTERNAL , NET_NO_SPACE
*/
2014-12-08 09:40:08 +00:00
static int sceNetAdhocPtpSend ( int id , u32 dataAddr , u32 dataSizeAddr , int timeout , int flag ) {
2014-07-31 18:55:42 +00:00
DEBUG_LOG ( SCENET , " sceNetAdhocPtpSend(%d,%08x,%08x,%d,%d) at %08x " , id , dataAddr , dataSizeAddr , timeout , flag , currentMIPS - > pc ) ;
2013-12-04 10:07:00 +00:00
if ( ! g_Config . bEnableWlan ) {
return 0 ;
}
2013-11-28 06:05:11 +00:00
int * len = ( int * ) Memory : : GetPointer ( dataSizeAddr ) ;
const char * data = Memory : : GetCharPointer ( dataAddr ) ;
2013-10-29 21:06:26 +00:00
// Library is initialized
2013-12-05 19:43:30 +00:00
if ( netAdhocInited ) {
2013-10-29 21:06:26 +00:00
// Valid Socket
2013-12-05 19:43:30 +00:00
if ( id > 0 & & id < = 255 & & ptp [ id - 1 ] ! = NULL ) {
2013-10-29 21:06:26 +00:00
// Cast Socket
SceNetAdhocPtpStat * socket = ptp [ id - 1 ] ;
// Connected Socket
2014-07-31 18:55:42 +00:00
if ( socket - > state = = ADHOC_PTP_STATE_ESTABLISHED ) {
2013-10-29 21:06:26 +00:00
// Valid Arguments
2013-12-05 19:43:30 +00:00
if ( data ! = NULL & & len ! = NULL & & * len > 0 ) {
2013-10-29 21:06:26 +00:00
// Schedule Timeout Removal
2013-12-05 19:43:30 +00:00
if ( flag ) timeout = 0 ;
2013-10-29 21:06:26 +00:00
// Apply Send Timeout Settings to Socket
2013-11-25 01:57:08 +00:00
setsockopt ( socket - > id , SOL_SOCKET , SO_SNDTIMEO , ( const char * ) & timeout , sizeof ( timeout ) ) ;
2013-10-29 21:06:26 +00:00
// Acquire Network Lock
// _acquireNetworkLock();
// Send Data
2013-11-28 06:05:11 +00:00
changeBlockingMode ( socket - > id , flag ) ;
2013-10-29 21:06:26 +00:00
int sent = send ( socket - > id , data , * len , 0 ) ;
2013-11-28 06:05:11 +00:00
int error = errno ;
changeBlockingMode ( socket - > id , 0 ) ;
2013-10-29 21:06:26 +00:00
// Free Network Lock
// _freeNetworkLock();
// Success
2013-12-05 19:43:30 +00:00
if ( sent > 0 ) {
2013-10-29 21:06:26 +00:00
// Save Length
* len = sent ;
2014-07-31 18:55:42 +00:00
uint8_t * smac = ( uint8_t * ) & socket - > paddr ;
INFO_LOG ( SCENET , " sceNetAdhocPtpSend[%i:%u]: Sent %u bytes to %02X:%02X:%02X:%02X:%02X:%02X:%u " , id , socket - > lport , sent , smac [ 0 ] , smac [ 1 ] , smac [ 2 ] , smac [ 3 ] , smac [ 4 ] , smac [ 5 ] , socket - > pport ) ;
2013-10-29 21:06:26 +00:00
// Return Success
return 0 ;
}
// Non-Critical Error
2013-12-05 19:43:30 +00:00
else if ( sent = = - 1 & & error = = EAGAIN ) {
2013-10-29 21:06:26 +00:00
// Blocking Situation
2013-12-05 19:43:30 +00:00
if ( flag ) return ERROR_NET_ADHOC_WOULD_BLOCK ;
2013-10-29 21:06:26 +00:00
// Timeout
return ERROR_NET_ADHOC_TIMEOUT ;
}
// Change Socket State
2014-07-31 18:55:42 +00:00
socket - > state = ADHOC_PTP_STATE_CLOSED ;
2013-10-29 21:06:26 +00:00
// Disconnected
return ERROR_NET_ADHOC_DISCONNECTED ;
}
// Invalid Arguments
return ERROR_NET_ADHOC_INVALID_ARG ;
}
// Not connected
return ERROR_NET_ADHOC_NOT_CONNECTED ;
}
// Invalid Socket
return ERROR_NET_ADHOC_INVALID_SOCKET_ID ;
}
// Library is uninitialized
return ERROR_NET_ADHOC_NOT_INITIALIZED ;
2013-09-06 23:53:51 +00:00
}
2013-10-29 21:06:26 +00:00
/**
* Adhoc Emulator PTP Receiver
* @ param id Socket File Descriptor
* @ param buf Data Buffer
* @ param len IN : Buffersize OUT : Received Data ( in Bytes )
* @ param timeout Receive Timeout ( in Microseconds )
* @ param flag Nonblocking Flag
* @ return 0 on success or . . . ADHOC_NOT_INITIALIZED , ADHOC_INVALID_ARG , ADHOC_INVALID_SOCKET_ID , ADHOC_SOCKET_DELETED , ADHOC_SOCKET_ALERTED , ADHOC_WOULD_BLOCK , ADHOC_TIMEOUT , ADHOC_THREAD_ABORTED , ADHOC_DISCONNECTED , NET_INTERNAL
*/
2014-12-08 09:40:08 +00:00
static int sceNetAdhocPtpRecv ( int id , u32 dataAddr , u32 dataSizeAddr , int timeout , int flag ) {
2014-01-03 18:32:59 +00:00
DEBUG_LOG ( SCENET , " sceNetAdhocPtpRecv(%d,%08x,%08x,%d,%d) " , id , dataAddr , dataSizeAddr , timeout , flag ) ;
2013-12-04 10:07:00 +00:00
if ( ! g_Config . bEnableWlan ) {
return 0 ;
}
void * buf = ( void * ) Memory : : GetPointer ( dataAddr ) ;
2013-11-28 06:05:11 +00:00
int * len = ( int * ) Memory : : GetPointer ( dataSizeAddr ) ;
2013-10-29 21:06:26 +00:00
// Library is initialized
2013-12-05 19:43:30 +00:00
if ( netAdhocInited ) {
2013-10-29 21:06:26 +00:00
// Valid Socket
2014-07-31 18:55:42 +00:00
if ( id > 0 & & id < = 255 & & ptp [ id - 1 ] ! = NULL & & ptp [ id - 1 ] - > state = = ADHOC_PTP_STATE_ESTABLISHED ) {
2013-10-29 21:06:26 +00:00
// Cast Socket
SceNetAdhocPtpStat * socket = ptp [ id - 1 ] ;
// Valid Arguments
2013-12-05 19:43:30 +00:00
if ( buf ! = NULL & & len ! = NULL & & * len > 0 ) {
2013-10-29 21:06:26 +00:00
// Schedule Timeout Removal
2013-12-05 19:43:30 +00:00
if ( flag ) timeout = 0 ;
2013-10-29 21:06:26 +00:00
// Apply Send Timeout Settings to Socket
2013-11-25 01:57:08 +00:00
setsockopt ( socket - > id , SOL_SOCKET , SO_RCVTIMEO , ( const char * ) & timeout , sizeof ( timeout ) ) ;
2013-10-29 21:06:26 +00:00
// Acquire Network Lock
// _acquireNetworkLock();
// Receive Data
2013-11-28 06:05:11 +00:00
changeBlockingMode ( socket - > id , flag ) ;
2013-11-25 01:57:08 +00:00
int received = recv ( socket - > id , ( char * ) buf , * len , 0 ) ;
2013-11-28 06:05:11 +00:00
int error = errno ;
changeBlockingMode ( socket - > id , 0 ) ;
2013-10-29 21:06:26 +00:00
// Free Network Lock
// _freeNetworkLock();
// Received Data
2013-12-05 19:43:30 +00:00
if ( received > 0 ) {
2013-10-29 21:06:26 +00:00
// Save Length
* len = received ;
2014-07-31 18:55:42 +00:00
uint8_t * smac = ( uint8_t * ) & socket - > paddr ;
INFO_LOG ( SCENET , " sceNetAdhocPtpRecv[%i:%u]: Received %u bytes from %02X:%02X:%02X:%02X:%02X:%02X:%u " , id , socket - > lport , received , smac [ 0 ] , smac [ 1 ] , smac [ 2 ] , smac [ 3 ] , smac [ 4 ] , smac [ 5 ] , socket - > pport ) ;
2013-10-29 21:06:26 +00:00
// Return Success
return 0 ;
}
// Non-Critical Error
2013-12-05 19:43:30 +00:00
else if ( received = = - 1 & & error = = EAGAIN ) {
2013-10-29 21:06:26 +00:00
// Blocking Situation
2013-12-05 19:43:30 +00:00
if ( flag ) return ERROR_NET_ADHOC_WOULD_BLOCK ;
2013-10-29 21:06:26 +00:00
// Timeout
return ERROR_NET_ADHOC_TIMEOUT ;
}
// Change Socket State
2014-07-31 18:55:42 +00:00
socket - > state = ADHOC_PTP_STATE_CLOSED ;
2013-10-29 21:06:26 +00:00
// Disconnected
return ERROR_NET_ADHOC_DISCONNECTED ;
}
// Invalid Arguments
return ERROR_NET_ADHOC_INVALID_ARG ;
}
// Invalid Socket
return ERROR_NET_ADHOC_INVALID_SOCKET_ID ;
}
// Library is uninitialized
return ERROR_NET_ADHOC_NOT_INITIALIZED ;
2013-09-06 23:53:51 +00:00
}
2013-10-29 21:06:26 +00:00
/**
* Adhoc Emulator PTP Flusher
* @ param id Socket File Descriptor
* @ param timeout Flush Timeout ( in Microseconds )
* @ param flag Nonblocking Flag
* @ return 0 on success or . . . ADHOC_NOT_INITIALIZED , ADHOC_INVALID_ARG , ADHOC_INVALID_SOCKET_ID , ADHOC_SOCKET_DELETED , ADHOC_SOCKET_ALERTED , ADHOC_WOULD_BLOCK , ADHOC_TIMEOUT , ADHOC_THREAD_ABORTED , ADHOC_DISCONNECTED , ADHOC_NOT_CONNECTED , NET_INTERNAL
*/
2014-12-08 09:40:08 +00:00
static int sceNetAdhocPtpFlush ( int id , int timeout , int nonblock ) {
2014-07-31 18:55:42 +00:00
DEBUG_LOG ( SCENET , " sceNetAdhocPtpFlush(%d,%d,%d) at %08x " , id , timeout , nonblock , currentMIPS - > pc ) ;
2013-12-04 10:07:00 +00:00
if ( ! g_Config . bEnableWlan ) {
return 0 ;
}
2013-10-29 21:06:26 +00:00
// Library initialized
2013-12-05 19:43:30 +00:00
if ( netAdhocInited ) {
2013-10-29 21:06:26 +00:00
// Valid Socket
2013-12-05 19:43:30 +00:00
if ( id > 0 & & id < = 255 & & ptp [ id - 1 ] ! = NULL ) {
2013-10-29 21:06:26 +00:00
// Dummy Result
return 0 ;
}
// Invalid Socket
return ERROR_NET_ADHOC_INVALID_SOCKET_ID ;
}
// Library uninitialized
return ERROR_NET_ADHOC_NOT_INITIALIZED ;
2013-09-06 23:53:51 +00:00
}
2014-12-08 09:40:08 +00:00
static int sceNetAdhocGameModeCreateMaster ( u32 data , int size ) {
2014-06-24 16:43:03 +00:00
ERROR_LOG ( SCENET , " UNIMPL sceNetAdhocGameModeCreateMaster(%08x, %i) at %08x " , data , size , currentMIPS - > pc ) ;
2013-11-28 06:05:11 +00:00
return - 1 ;
2013-09-06 23:53:51 +00:00
}
2014-12-08 09:40:08 +00:00
static int sceNetAdhocGameModeCreateReplica ( const char * mac , u32 data , int size ) {
2014-06-24 16:43:03 +00:00
ERROR_LOG ( SCENET , " UNIMPL sceNetAdhocGameModeCreateReplica(%s, %08x, %i) at %08x " , mac , data , size , currentMIPS - > pc ) ;
2013-11-28 06:05:11 +00:00
return - 1 ;
2013-09-06 23:53:51 +00:00
}
2014-12-08 09:40:08 +00:00
static int sceNetAdhocGameModeUpdateMaster ( ) {
2013-11-28 06:05:11 +00:00
ERROR_LOG ( SCENET , " UNIMPL sceNetAdhocGameModeUpdateMaster() " ) ;
return - 1 ;
2013-09-06 23:53:51 +00:00
}
2014-12-08 09:40:08 +00:00
static int sceNetAdhocGameModeDeleteMaster ( ) {
2013-11-28 06:05:11 +00:00
ERROR_LOG ( SCENET , " UNIMPL sceNetAdhocGameModeDeleteMaster() " ) ;
return - 1 ;
2013-09-06 23:53:51 +00:00
}
2014-12-08 09:40:08 +00:00
static int sceNetAdhocGameModeUpdateReplica ( int id , u32 infoAddr ) {
2013-11-28 06:05:11 +00:00
ERROR_LOG ( SCENET , " UNIMPL sceNetAdhocGameModeUpdateReplica(%i, %08x) " , id , infoAddr ) ;
return - 1 ;
2013-09-06 23:53:51 +00:00
}
2014-12-08 09:40:08 +00:00
static int sceNetAdhocGameModeDeleteReplica ( int id ) {
2013-11-28 06:05:11 +00:00
ERROR_LOG ( SCENET , " UNIMPL sceNetAdhocGameModeDeleteReplica(%i) " , id ) ;
return - 1 ;
2013-09-06 23:53:51 +00:00
}
2014-07-31 18:55:42 +00:00
int sceNetAdhocGetSocketAlert ( int id , u32 flagPtr ) {
ERROR_LOG ( SCENET , " UNIMPL sceNetAdhocGetSocketAlert(%i, %08x) " , id , flagPtr ) ;
// Dummy Value
if ( Memory : : IsValidAddress ( flagPtr ) ) {
s32_le * flag = ( s32_le * ) Memory : : GetPointer ( flagPtr ) ;
* flag = 0 ;
}
// Dummy Result
2013-11-28 06:05:11 +00:00
return 0 ;
2013-09-06 23:53:51 +00:00
}
2014-07-31 18:55:42 +00:00
int sceNetAdhocMatchingStop ( int matchingId ) {
WARN_LOG ( SCENET , " UNTESTED sceNetAdhocMatchingStop(%i) at %08x " , matchingId , currentMIPS - > pc ) ;
//if (!g_Config.bEnableWlan)
// return -1;
2013-11-28 06:05:11 +00:00
2014-07-31 18:55:42 +00:00
SceNetAdhocMatchingContext * item = findMatchingContext ( matchingId ) ;
2013-11-28 06:05:11 +00:00
2014-07-31 18:55:42 +00:00
if ( item ! = NULL ) {
item - > inputRunning = false ;
if ( item - > inputThread . joinable ( ) ) {
item - > inputThread . join ( ) ;
}
item - > eventRunning = false ;
if ( item - > eventThread . joinable ( ) ) {
item - > eventThread . join ( ) ;
}
// Stop fake PSP Thread
//__KernelStopThread(item->matching_thid, SCE_KERNEL_ERROR_THREAD_TERMINATED, "AdhocMatching stopped");
//item->matchingThread->Terminate();
// Multithreading Lock
peerlock . lock ( ) ;
// Remove your own MAC, or All memebers, or don't remove at all or we should do this on MatchingDelete ?
clearPeerList ( item ) ; //deleteAllMembers(item);
item - > running = 0 ;
netAdhocMatchingStarted - - ;
// Multithreading Unlock
peerlock . unlock ( ) ;
}
return 0 ;
}
int sceNetAdhocMatchingDelete ( int matchingId ) {
// WLAN might be disabled in the middle of successfull multiplayer, but we still need to cleanup right?
// Previous Context Reference
SceNetAdhocMatchingContext * prev = NULL ;
// Multithreading Lock
peerlock . lock ( ) ; //contextlock.lock();
// Context Pointer
SceNetAdhocMatchingContext * item = contexts ;
// Iterate contexts
for ( ; item ! = NULL ; item = item - > next ) {
// Found matching ID
if ( item - > id = = matchingId ) {
// Unlink Left (Beginning)
if ( prev = = NULL ) contexts = item - > next ;
// Unlink Left (Other)
else prev - > next = item - > next ;
// Stop it first if it's still running
if ( item - > running ) {
sceNetAdhocMatchingStop ( matchingId ) ;
}
// Delete the Fake PSP Thread
//__KernelDeleteThread(item->matching_thid, SCE_KERNEL_ERROR_THREAD_TERMINATED, "AdhocMatching deleted");
//delete item->matchingThread;
// Make sure nobody locking/using the socket
item - > socketlock - > lock ( ) ;
// Delete the socket
sceNetAdhocPdpDelete ( item - > socket , 0 ) ; // item->connected = (sceNetAdhocPdpDelete(item->socket, 0) < 0);
item - > socketlock - > unlock ( ) ;
// Free allocated memories
free ( item - > hello ) ;
free ( item - > rxbuf ) ;
clearPeerList ( item ) ; //deleteAllMembers(item);
// Destroy locks
item - > eventlock - > lock ( ) ; // Make sure it's not locked when being deleted
item - > eventlock - > unlock ( ) ;
delete item - > eventlock ;
item - > inputlock - > lock ( ) ; // Make sure it's not locked when being deleted
item - > inputlock - > unlock ( ) ;
delete item - > inputlock ;
item - > socketlock - > lock ( ) ; // Make sure it's not locked when being deleted
item - > socketlock - > unlock ( ) ;
delete item - > socketlock ;
// Free item context memory
free ( item ) ;
item = NULL ;
// Stop Search
break ;
}
// Set Previous Reference
prev = item ;
2013-11-28 06:05:11 +00:00
}
2014-07-31 18:55:42 +00:00
// Multithreading Unlock
peerlock . unlock ( ) ; //contextlock.unlock();
WARN_LOG ( SCENET , " UNTESTED sceNetAdhocMatchingDelete(%i) at %08x " , matchingId , currentMIPS - > pc ) ;
return 0 ;
}
int sceNetAdhocMatchingInit ( u32 memsize ) {
WARN_LOG ( SCENET , " sceNetAdhocMatchingInit(%d) at %08x " , memsize , currentMIPS - > pc ) ;
// Uninitialized Library
if ( netAdhocMatchingInited ) return ERROR_NET_ADHOC_MATCHING_ALREADY_INITIALIZED ;
// Save Fake Pool Size
fakePoolSize = memsize ;
// Initialize Library
netAdhocMatchingInited = true ;
// Return Success
return 0 ;
2013-09-07 09:06:06 +00:00
}
int sceNetAdhocMatchingTerm ( ) {
2014-06-24 16:43:03 +00:00
// Should we cleanup all created matching contexts first? just in case there are games that doesn't delete them before calling this
if ( netAdhocMatchingInited ) {
2014-07-31 18:55:42 +00:00
// Delete all Matching contexts
SceNetAdhocMatchingContext * next = NULL ;
SceNetAdhocMatchingContext * context = contexts ;
while ( context ! = NULL ) {
next = context - > next ;
if ( context - > running ) sceNetAdhocMatchingStop ( context - > id ) ;
sceNetAdhocMatchingDelete ( context - > id ) ;
context = next ;
}
2014-06-24 16:43:03 +00:00
}
2014-07-31 18:55:42 +00:00
WARN_LOG ( SCENET , " UNTESTED sceNetAdhocMatchingTerm() " ) ;
2013-11-28 06:05:11 +00:00
netAdhocMatchingInited = false ;
2013-09-07 09:06:06 +00:00
2013-11-28 06:05:11 +00:00
return 0 ;
2013-09-07 09:06:06 +00:00
}
// Presumably returns a "matchingId".
2014-12-08 09:40:08 +00:00
static int sceNetAdhocMatchingCreate ( int mode , int maxnum , int port , int rxbuflen , int hello_int , int keepalive_int , int init_count , int rexmt_int , u32 callbackAddr ) {
2014-07-31 18:55:42 +00:00
WARN_LOG ( SCENET , " sceNetAdhocMatchingCreate(mode=%i, maxnum=%i, port=%i, rxbuflen=%i, hello=%i, keepalive=%i, initcount=%i, rexmt=%i, callbackAddr=%08x) at %08x " , mode , maxnum , port , rxbuflen , hello_int , keepalive_int , init_count , rexmt_int , callbackAddr , currentMIPS - > pc ) ;
2013-12-04 10:07:00 +00:00
if ( ! g_Config . bEnableWlan ) {
return - 1 ;
}
2014-07-31 18:55:42 +00:00
2013-11-28 06:05:11 +00:00
SceNetAdhocMatchingHandler handler ;
handler . entryPoint = callbackAddr ;
// Library initialized
2013-12-05 19:43:30 +00:00
if ( netAdhocMatchingInited ) {
2013-11-28 06:05:11 +00:00
// Valid Member Limit
2013-12-05 19:43:30 +00:00
if ( maxnum > 1 & & maxnum < = 16 ) {
2013-11-28 06:05:11 +00:00
// Valid Receive Buffer size
2013-12-05 19:43:30 +00:00
if ( rxbuflen > = 1024 ) {
2013-11-28 06:05:11 +00:00
// Valid Arguments
2013-12-05 19:43:30 +00:00
if ( mode > = 1 & & mode < = 3 ) {
2013-11-28 06:05:11 +00:00
// Iterate Matching Contexts
2013-12-05 19:43:30 +00:00
SceNetAdhocMatchingContext * item = contexts ; for ( ; item ! = NULL ; item = item - > next ) {
2013-11-28 06:05:11 +00:00
// Port Match found
2013-12-05 19:43:30 +00:00
if ( item - > port = = port ) return ERROR_NET_ADHOC_MATCHING_PORT_IN_USE ;
2013-11-28 06:05:11 +00:00
}
// Allocate Context Memory
SceNetAdhocMatchingContext * context = ( SceNetAdhocMatchingContext * ) malloc ( sizeof ( SceNetAdhocMatchingContext ) ) ;
// Allocated Memory
2013-12-05 19:43:30 +00:00
if ( context ! = NULL ) {
2013-11-28 06:05:11 +00:00
// Create PDP Socket
SceNetEtherAddr localmac ; getLocalMac ( & localmac ) ;
const char * mac = ( const char * ) & localmac . data ;
int socket = sceNetAdhocPdpCreate ( mac , ( uint32_t ) port , rxbuflen , 0 ) ;
// Created PDP Socket
2013-12-05 19:43:30 +00:00
if ( socket > 0 ) {
2013-11-28 06:05:11 +00:00
// Clear Memory
memset ( context , 0 , sizeof ( SceNetAdhocMatchingContext ) ) ;
// Allocate Receive Buffer
context - > rxbuf = ( uint8_t * ) malloc ( rxbuflen ) ;
// Allocated Memory
2013-12-05 19:43:30 +00:00
if ( context - > rxbuf ! = NULL ) {
2013-11-28 06:05:11 +00:00
// Clear Memory
memset ( context - > rxbuf , 0 , rxbuflen ) ;
// Fill in Context Data
context - > id = findFreeMatchingID ( ) ;
context - > mode = mode ;
context - > maxpeers = maxnum ;
context - > port = port ;
context - > socket = socket ;
context - > rxbuflen = rxbuflen ;
context - > resendcounter = init_count ;
2014-07-31 18:55:42 +00:00
context - > resend_int = rexmt_int ; // used as ack timeout on lost packet (ie. not receiving anything after sending)?
context - > hello_int = hello_int ; // client might set this to 0
if ( keepalive_int < 1 ) context - > keepalive_int = PSP_ADHOCCTL_PING_TIMEOUT ; else context - > keepalive_int = keepalive_int ; // client might set this to 0
context - > keepalivecounter = init_count ; // used to multiply keepalive_int as timeout
context - > timeout = ( keepalive_int * init_count ) ;
if ( context - > timeout < 5000000 ) context - > timeout = 5000000 ; // For internet play we need higher timeout than what the game wanted
2013-11-28 06:05:11 +00:00
context - > handler = handler ;
// Fill in Selfpeer
context - > mac = localmac ;
2014-07-31 18:55:42 +00:00
// Create locks
context - > socketlock = new recursive_mutex ;
context - > eventlock = new recursive_mutex ;
context - > inputlock = new recursive_mutex ;
// Create fake thread
//#define PSP_THREAD_ATTR_KERNEL 0x00001000 // PSP_THREAD_ATTR_KERNEL is located in sceKernelThread.cpp instead of sceKernelThread.h :(
//context->matching_thid = __KernelCreateThreadInternal("AdhocMatching", 0, idleThreadHackAddr, 0x7f, 4096, PSP_THREAD_ATTR_KERNEL);
//context->matchingThread = new HLEHelperThread("AdhocMatching", "AdhocMatchingMod", "AdhocMatchingFunc", 0x7f, 4096); //8192
2014-06-24 16:43:03 +00:00
// Multithreading Lock
peerlock . lock ( ) ; //contextlock.lock();
2014-07-31 18:55:42 +00:00
// Add Callback Handler
context - > handler . entryPoint = callbackAddr ;
2014-06-24 16:43:03 +00:00
2013-11-28 06:05:11 +00:00
// Link Context
2014-06-24 16:43:03 +00:00
//context->connected = true;
2013-11-28 06:05:11 +00:00
context - > next = contexts ;
contexts = context ;
2014-06-24 16:43:03 +00:00
// Multithreading UnLock
peerlock . unlock ( ) ; //contextlock.unlock();
2013-11-28 06:05:11 +00:00
// Return Matching ID
return context - > id ;
}
// Close PDP Socket
2014-06-24 16:43:03 +00:00
sceNetAdhocPdpDelete ( socket , 0 ) ; // context->connected = (sceNetAdhocPdpDelete(socket, 0) < 0);
2013-11-28 06:05:11 +00:00
}
// Free Memory
free ( context ) ;
// Port in use
2014-06-24 16:43:03 +00:00
if ( socket < 1 ) return ERROR_NET_ADHOC_MATCHING_PORT_IN_USE ; // ERROR_NET_ADHOC_MATCHING_NOT_INITIALIZED; // -1; // ERROR_NET_ADHOC_MATCHING_NOT_ESTABLISHED;
2013-11-28 06:05:11 +00:00
}
// Out of Memory
return ERROR_NET_ADHOC_MATCHING_NO_SPACE ;
}
// InvalidERROR_NET_Arguments
return ERROR_NET_ADHOC_MATCHING_INVALID_ARG ;
}
// Invalid Receive Buffer Size
return ERROR_NET_ADHOC_MATCHING_RXBUF_TOO_SHORT ;
}
// Invalid Member Limit
return ERROR_NET_ADHOC_MATCHING_INVALID_MAXNUM ;
}
// Uninitialized Library
return ERROR_NET_ADHOC_MATCHING_NOT_INITIALIZED ;
2013-09-07 09:06:06 +00:00
}
2014-06-24 16:43:03 +00:00
// TODO: Should we execute the callback used to create the Matching Id if it's a valid address?
2014-12-08 09:40:08 +00:00
static int sceNetAdhocMatchingStart ( int matchingId , int evthPri , int evthStack , int inthPri , int inthStack , int optLen , u32 optDataAddr ) {
2014-07-31 18:55:42 +00:00
WARN_LOG ( SCENET , " UNTESTED sceNetAdhocMatchingStart(%i, %i, %i, %i, %i, %i, %08x) at %08x " , matchingId , evthPri , evthStack , inthPri , inthStack , optLen , optDataAddr , currentMIPS - > pc ) ;
2014-05-24 23:57:02 +00:00
if ( ! g_Config . bEnableWlan )
return - 1 ;
2014-06-24 16:43:03 +00:00
2014-07-31 18:55:42 +00:00
// Multithreading Lock
peerlock . lock ( ) ;
2014-06-24 16:43:03 +00:00
SceNetAdhocMatchingContext * item = findMatchingContext ( matchingId ) ;
2014-07-31 18:55:42 +00:00
2014-06-24 16:43:03 +00:00
if ( item ! = NULL ) {
2014-07-31 18:55:42 +00:00
//sceNetAdhocMatchingSetHelloOpt(matchingId, optLen, optDataAddr); //SetHelloOpt only works when context is running
2014-06-24 16:43:03 +00:00
if ( ( optLen > 0 ) & & Memory : : IsValidAddress ( optDataAddr ) ) {
// Allocate the memory and copy the content
if ( item - > hello ! = NULL ) free ( item - > hello ) ;
2014-07-31 18:55:42 +00:00
item - > hello = ( uint8_t * ) malloc ( optLen ) ;
if ( item - > hello ! = NULL ) {
2014-06-24 16:43:03 +00:00
Memory : : Memcpy ( item - > hello , optDataAddr , optLen ) ;
2014-07-31 18:55:42 +00:00
item - > hellolen = optLen ;
item - > helloAddr = optDataAddr ;
}
//else return ERROR_NET_ADHOC_MATCHING_NO_SPACE; //Faking success to prevent GTA:VCS from stuck unable to choose host/join menu
2014-06-24 16:43:03 +00:00
}
2014-07-31 18:55:42 +00:00
//else return ERROR_NET_ADHOC_MATCHING_INVALID_ARG; // ERROR_NET_ADHOC_MATCHING_INVALID_OPTLEN; // Returning Not Success will cause GTA:VC stuck unable to choose host/join menu
//Add your own MAC as a member (only if it's empty?)
/*SceNetAdhocMatchingMemberInternal * peer = addMember(item, &item->mac);
switch ( item - > mode ) {
case PSP_ADHOC_MATCHING_MODE_PARENT :
peer - > state = PSP_ADHOC_MATCHING_PEER_OFFER ;
break ;
case PSP_ADHOC_MATCHING_MODE_CHILD :
peer - > state = PSP_ADHOC_MATCHING_PEER_CHILD ;
break ;
case PSP_ADHOC_MATCHING_MODE_P2P :
peer - > state = PSP_ADHOC_MATCHING_PEER_P2P ;
} */
2014-06-24 16:43:03 +00:00
2014-07-31 18:55:42 +00:00
// Start the Fake PSP Thread
//__KernelStartThread(item->matching_thid, 0, 0);
//item->matchingThread->Start(0, 0);
2014-06-24 16:43:03 +00:00
2014-07-31 18:55:42 +00:00
//Create the threads
if ( ! item - > eventRunning ) {
item - > eventRunning = true ;
item - > eventThread = std : : thread ( matchingEventThread , matchingId ) ;
}
if ( ! item - > inputRunning ) {
item - > inputRunning = true ;
item - > inputThread = std : : thread ( matchingInputThread , matchingId ) ;
}
item - > running = 1 ;
netAdhocMatchingStarted + + ;
2014-06-24 16:43:03 +00:00
}
2014-07-31 18:55:42 +00:00
//else return ERROR_NET_ADHOC_MATCHING_INVALID_ID; //Faking success to prevent GTA:VCS from stuck unable to choose host/join menu
// Multithreading Unlock
peerlock . unlock ( ) ;
2014-06-24 16:43:03 +00:00
2014-05-24 23:57:02 +00:00
return 0 ;
2013-09-07 09:06:06 +00:00
}
2014-07-31 18:55:42 +00:00
static int sceNetAdhocMatchingSelectTarget ( int matchingId , const char * macAddress , int optLen , u32 optDataPtr ) {
WARN_LOG ( SCENET , " UNTESTED sceNetAdhocMatchingSelectTarget(%i, %s, %i, %08x) at %08x " , matchingId , macAddress , optLen , optDataPtr , currentMIPS - > pc ) ;
2014-05-24 23:57:02 +00:00
if ( ! g_Config . bEnableWlan )
return - 1 ;
2014-07-31 18:55:42 +00:00
// Initialized Library
if ( netAdhocMatchingInited )
{
// Valid Arguments
if ( macAddress ! = NULL )
{
SceNetEtherAddr * target = ( SceNetEtherAddr * ) macAddress ;
2014-06-24 16:43:03 +00:00
2014-07-31 18:55:42 +00:00
// Find Matching Context for ID
SceNetAdhocMatchingContext * context = findMatchingContext ( matchingId ) ;
2014-06-24 16:43:03 +00:00
2014-07-31 18:55:42 +00:00
// Found Matching Context
if ( context ! = NULL )
{
// Running Context
if ( context - > running )
{
// Search Result
SceNetAdhocMatchingMemberInternal * peer = findPeer ( context , ( SceNetEtherAddr * ) target ) ;
// Found Peer in List
if ( peer ! = NULL )
{
// Valid Optional Data Length
2015-01-04 13:09:41 +00:00
if ( ( optLen = = 0 & & optDataPtr = = 0 ) | | ( optLen > 0 & & optDataPtr ! = 0 ) )
2014-07-31 18:55:42 +00:00
{
void * opt = NULL ;
if ( Memory : : IsValidAddress ( optDataPtr ) ) opt = Memory : : GetPointer ( optDataPtr ) ;
// Host Mode
if ( context - > mode = = PSP_ADHOC_MATCHING_MODE_PARENT )
{
// Already Connected
if ( peer - > state = = PSP_ADHOC_MATCHING_PEER_CHILD ) return ERROR_NET_ADHOC_MATCHING_ALREADY_ESTABLISHED ;
// Not enough space
if ( countChildren ( context ) = = ( context - > maxpeers - 1 ) ) return ERROR_NET_ADHOC_MATCHING_EXCEED_MAXNUM ;
// Requesting Peer
if ( peer - > state = = PSP_ADHOC_MATCHING_PEER_INCOMING_REQUEST )
{
// Accept Peer in Group
peer - > state = PSP_ADHOC_MATCHING_PEER_CHILD ;
// Sending order may need to be reversed since Stack appends to the front, so the order will be switched around.
// Tell Children about new Sibling
sendBirthMessage ( context , peer ) ;
2014-08-11 16:25:24 +00:00
// Spawn Established Event
//spawnLocalEvent(context, PSP_ADHOC_MATCHING_EVENT_ESTABLISHED, target, 0, NULL);
2014-07-31 18:55:42 +00:00
// Send Accept Confirmation to Peer
sendAcceptMessage ( context , peer , optLen , opt ) ;
// Return Success
return 0 ;
}
}
2014-06-24 16:43:03 +00:00
2014-07-31 18:55:42 +00:00
// Client Mode
else if ( context - > mode = = PSP_ADHOC_MATCHING_MODE_CHILD )
{
// Already connected
if ( findParent ( context ) ! = NULL ) return ERROR_NET_ADHOC_MATCHING_ALREADY_ESTABLISHED ;
2013-09-07 09:06:06 +00:00
2014-07-31 18:55:42 +00:00
// Outgoing Request in Progress
if ( findOutgoingRequest ( context ) ! = NULL ) return ERROR_NET_ADHOC_MATCHING_REQUEST_IN_PROGRESS ;
2014-06-24 16:43:03 +00:00
2014-07-31 18:55:42 +00:00
// Valid Offer
if ( peer - > state = = PSP_ADHOC_MATCHING_PEER_OFFER )
{
// Switch into Join Request Mode
peer - > state = PSP_ADHOC_MATCHING_PEER_OUTGOING_REQUEST ;
2014-06-24 16:43:03 +00:00
2014-07-31 18:55:42 +00:00
// Send Join Request to Peer
sendJoinRequest ( context , peer , optLen , opt ) ;
2014-06-24 16:43:03 +00:00
2014-07-31 18:55:42 +00:00
// Return Success
return 0 ;
}
}
2014-06-24 16:43:03 +00:00
2014-07-31 18:55:42 +00:00
// P2P Mode
else
{
// Already connected
if ( findP2P ( context ) ! = NULL ) return ERROR_NET_ADHOC_MATCHING_ALREADY_ESTABLISHED ;
2014-06-24 16:43:03 +00:00
2014-07-31 18:55:42 +00:00
// Outgoing Request in Progress
if ( findOutgoingRequest ( context ) ! = NULL ) return ERROR_NET_ADHOC_MATCHING_REQUEST_IN_PROGRESS ;
2014-06-24 16:43:03 +00:00
2014-07-31 18:55:42 +00:00
// Join Request Mode
if ( peer - > state = = PSP_ADHOC_MATCHING_PEER_OFFER )
{
// Switch into Join Request Mode
peer - > state = PSP_ADHOC_MATCHING_PEER_OUTGOING_REQUEST ;
2014-06-24 16:43:03 +00:00
2014-07-31 18:55:42 +00:00
// Send Join Request to Peer
sendJoinRequest ( context , peer , optLen , opt ) ;
2014-06-24 16:43:03 +00:00
2014-07-31 18:55:42 +00:00
// Return Success
return 0 ;
}
// Requesting Peer
else if ( peer - > state = = PSP_ADHOC_MATCHING_PEER_INCOMING_REQUEST )
{
// Accept Peer in Group
peer - > state = PSP_ADHOC_MATCHING_PEER_P2P ;
2014-08-11 16:25:24 +00:00
// Tell Children about new Sibling
//sendBirthMessage(context, peer);
2014-07-31 18:55:42 +00:00
// Send Accept Confirmation to Peer
sendAcceptMessage ( context , peer , optLen , opt ) ;
// Return Success
return 0 ;
}
}
// How did this happen?! It shouldn't!
return ERROR_NET_ADHOC_MATCHING_TARGET_NOT_READY ;
}
// Invalid Optional Data Length
return ERROR_NET_ADHOC_MATCHING_INVALID_OPTLEN ;
}
// Peer not found
return ERROR_NET_ADHOC_MATCHING_UNKNOWN_TARGET ;
}
// Idle Context
return ERROR_NET_ADHOC_MATCHING_NOT_RUNNING ;
}
// Invalid Matching ID
return ERROR_NET_ADHOC_MATCHING_INVALID_ID ;
2014-06-24 16:43:03 +00:00
}
2014-07-31 18:55:42 +00:00
// Invalid Arguments
return ERROR_NET_ADHOC_MATCHING_INVALID_ARG ;
2014-06-24 16:43:03 +00:00
}
2013-09-07 09:06:06 +00:00
2014-07-31 18:55:42 +00:00
// Uninitialized Library
return ERROR_NET_ADHOC_MATCHING_NOT_INITIALIZED ;
2013-09-07 09:06:06 +00:00
}
2014-07-31 18:55:42 +00:00
int sceNetAdhocMatchingCancelTargetWithOpt ( int matchingId , const char * macAddress , int optLen , u32 optDataPtr ) {
WARN_LOG ( SCENET , " UNTESTED sceNetAdhocMatchingCancelTargetWithOpt(%i, %s, %i, %08x) at %08x " , matchingId , macAddress , optLen , optDataPtr , currentMIPS - > pc ) ;
2014-05-24 23:57:02 +00:00
if ( ! g_Config . bEnableWlan )
return - 1 ;
2014-07-31 18:55:42 +00:00
// Initialized Library
if ( netAdhocMatchingInited )
{
SceNetEtherAddr * target = ( SceNetEtherAddr * ) macAddress ;
void * opt = NULL ;
if ( Memory : : IsValidAddress ( optDataPtr ) ) opt = Memory : : GetPointer ( optDataPtr ) ;
2013-09-07 09:06:06 +00:00
2014-07-31 18:55:42 +00:00
// Valid Arguments
if ( target ! = NULL & & ( ( optLen = = 0 & & opt = = NULL ) | | ( optLen > 0 & & opt ! = NULL ) ) )
{
// Find Matching Context
SceNetAdhocMatchingContext * context = findMatchingContext ( matchingId ) ;
// Found Matching Context
if ( context ! = NULL )
{
// Running Context
if ( context - > running )
{
// Find Peer
SceNetAdhocMatchingMemberInternal * peer = findPeer ( context , ( SceNetEtherAddr * ) target ) ;
// Found Peer
if ( peer ! = NULL )
{
// Valid Peer Mode
if ( ( context - > mode = = PSP_ADHOC_MATCHING_MODE_CHILD & & ( peer - > state = = PSP_ADHOC_MATCHING_PEER_PARENT | | peer - > state = = PSP_ADHOC_MATCHING_PEER_OUTGOING_REQUEST ) ) | |
( context - > mode = = PSP_ADHOC_MATCHING_MODE_PARENT & & ( peer - > state = = PSP_ADHOC_MATCHING_PEER_CHILD | | peer - > state = = PSP_ADHOC_MATCHING_PEER_INCOMING_REQUEST ) ) | |
( context - > mode = = PSP_ADHOC_MATCHING_MODE_P2P & & ( peer - > state = = PSP_ADHOC_MATCHING_PEER_P2P | | peer - > state = = PSP_ADHOC_MATCHING_PEER_INCOMING_REQUEST ) ) )
{
// Notify other Children of Death
if ( context - > mode = = PSP_ADHOC_MATCHING_MODE_PARENT & & peer - > state = = PSP_ADHOC_MATCHING_PEER_CHILD & & countConnectedPeers ( context ) > 1 )
{
// Send Death Message
sendDeathMessage ( context , peer ) ;
}
// Mark Peer as Canceled
peer - > state = PSP_ADHOC_MATCHING_PEER_CANCEL_IN_PROGRESS ;
// Send Cancel Event to Peer
sendCancelMessage ( context , peer , optLen , opt ) ;
// Delete Peer from List
// Can't delete here, Threads still need this data.
// deletePeer(context, peer);
// Return Success
return 0 ;
}
}
// Peer not found
//return ERROR_NET_ADHOC_MATCHING_UNKNOWN_TARGET;
// Faking success to prevent the game (ie. Soul Calibur) to repeatedly calling this function when the other player is disconnected
return 0 ;
}
// Context not running
return ERROR_NET_ADHOC_MATCHING_NOT_RUNNING ;
}
// Invalid Matching ID
return ERROR_NET_ADHOC_MATCHING_INVALID_ID ;
}
// Invalid Arguments
return ERROR_NET_ADHOC_MATCHING_INVALID_ARG ;
}
// Uninitialized Library
return ERROR_NET_ADHOC_MATCHING_NOT_INITIALIZED ;
}
2013-09-07 09:06:06 +00:00
2014-07-31 18:55:42 +00:00
int sceNetAdhocMatchingCancelTarget ( int matchingId , const char * macAddress ) {
WARN_LOG ( SCENET , " UNTESTED sceNetAdhocMatchingCancelTarget(%i, %s) " , matchingId , macAddress ) ;
2014-05-24 23:57:02 +00:00
if ( ! g_Config . bEnableWlan )
return - 1 ;
2015-01-04 13:09:41 +00:00
return sceNetAdhocMatchingCancelTargetWithOpt ( matchingId , macAddress , 0 , 0 ) ;
2014-07-31 18:55:42 +00:00
}
int sceNetAdhocMatchingGetHelloOpt ( int matchingId , u32 optLenAddr , u32 optDataAddr ) {
WARN_LOG ( SCENET , " UNTESTED sceNetAdhocMatchingGetHelloOpt(%i, %08x, %08x) " , matchingId , optLenAddr , optDataAddr ) ;
if ( ! g_Config . bEnableWlan )
return - 1 ;
if ( ! Memory : : IsValidAddress ( optLenAddr ) ) return ERROR_NET_ADHOC_MATCHING_INVALID_ARG ;
2015-03-10 17:56:09 +00:00
s32_le * optlen = PSPPointer < s32_le > : : Create ( optLenAddr ) ;
2014-07-31 18:55:42 +00:00
// Multithreading Lock
peerlock . lock ( ) ;
SceNetAdhocMatchingContext * item = findMatchingContext ( matchingId ) ;
if ( item ! = NULL ) {
// Get OptData
* optlen = item - > hellolen ;
if ( ( * optlen > 0 ) & & Memory : : IsValidAddress ( optDataAddr ) ) {
uint8_t * optdata = Memory : : GetPointer ( optDataAddr ) ;
memcpy ( optdata , item - > hello , * optlen ) ;
}
//else return ERROR_NET_ADHOC_MATCHING_INVALID_ARG;
}
//else return ERROR_NET_ADHOC_MATCHING_INVALID_ID;
// Multithreading Unlock
peerlock . unlock ( ) ;
2014-05-24 23:57:02 +00:00
return 0 ;
2013-09-07 09:06:06 +00:00
}
int sceNetAdhocMatchingSetHelloOpt ( int matchingId , int optLenAddr , u32 optDataAddr ) {
2014-06-24 16:43:03 +00:00
DEBUG_LOG ( SCENET , " UNTESTED sceNetAdhocMatchingSetHelloOpt(%i, %i, %08x) at %08x " , matchingId , optLenAddr , optDataAddr , currentMIPS - > pc ) ;
2014-05-24 23:57:02 +00:00
if ( ! g_Config . bEnableWlan )
return - 1 ;
2014-06-24 16:43:03 +00:00
2014-07-31 18:55:42 +00:00
if ( ! netAdhocMatchingInited ) return ERROR_NET_ADHOC_MATCHING_NOT_INITIALIZED ;
2014-06-24 16:43:03 +00:00
2014-07-31 18:55:42 +00:00
// Multithreading Lock
peerlock . lock ( ) ;
2014-06-24 16:43:03 +00:00
2014-07-31 18:55:42 +00:00
SceNetAdhocMatchingContext * context = findMatchingContext ( matchingId ) ;
// Multithreading Unlock
peerlock . unlock ( ) ;
// Found Context
if ( context ! = NULL )
{
// Valid Matching Modes
if ( context - > mode ! = PSP_ADHOC_MATCHING_MODE_CHILD )
{
// Running Context
if ( context - > running )
{
// Valid Optional Data Length
2015-01-04 13:09:41 +00:00
if ( ( optLenAddr = = 0 & & optDataAddr = = 0 ) | | ( optLenAddr > 0 & & optDataAddr ! = 0 ) )
2014-07-31 18:55:42 +00:00
{
// Grab Existing Hello Data
void * hello = context - > hello ;
// Free Previous Hello Data, or Reuse it
//free(hello);
// Allocation Required
if ( optLenAddr > 0 )
{
// Allocate Memory
if ( optLenAddr > context - > hellolen ) {
hello = realloc ( hello , optLenAddr ) ;
}
// Out of Memory
if ( hello = = NULL ) {
context - > hellolen = 0 ;
return ERROR_NET_ADHOC_MATCHING_NO_SPACE ;
}
// Clone Hello Data
//memcpy(hello, opt, optLenAddr);
Memory : : Memcpy ( hello , optDataAddr , optLenAddr ) ;
// Set Hello Data
context - > hello = ( uint8_t * ) hello ;
context - > hellolen = optLenAddr ;
context - > helloAddr = optDataAddr ;
}
else
{
// Delete Hello Data
context - > hellolen = 0 ;
context - > helloAddr = 0 ;
//free(context->hello); // Doesn't need to free it since it will be reused later
//context->hello = NULL;
}
// Return Success
return 0 ;
}
// Invalid Optional Data Length
return ERROR_NET_ADHOC_MATCHING_INVALID_OPTLEN ;
2014-06-24 16:43:03 +00:00
}
2014-07-31 18:55:42 +00:00
// Context not running
return ERROR_NET_ADHOC_MATCHING_NOT_RUNNING ;
2014-06-24 16:43:03 +00:00
}
2014-07-31 18:55:42 +00:00
// Invalid Matching Mode (Child)
return ERROR_NET_ADHOC_MATCHING_INVALID_MODE ;
}
2014-06-24 16:43:03 +00:00
2014-05-24 23:57:02 +00:00
return 0 ;
2013-09-07 09:06:06 +00:00
}
2014-12-08 09:40:08 +00:00
static int sceNetAdhocMatchingGetMembers ( int matchingId , u32 sizeAddr , u32 buf ) {
2014-06-24 16:43:03 +00:00
DEBUG_LOG ( SCENET , " UNTESTED sceNetAdhocMatchingGetMembers(%i, [%08x]=%i, %08x) at %08x " , matchingId , sizeAddr , Memory : : Read_U32 ( sizeAddr ) , buf , currentMIPS - > pc ) ;
2014-05-24 23:57:02 +00:00
if ( ! g_Config . bEnableWlan )
return - 1 ;
2014-06-24 16:43:03 +00:00
2014-07-31 18:55:42 +00:00
if ( ! netAdhocMatchingInited ) return ERROR_NET_ADHOC_MATCHING_NOT_INITIALIZED ;
2014-06-24 16:43:03 +00:00
// Minimum Argument
if ( ! Memory : : IsValidAddress ( sizeAddr ) ) return ERROR_NET_ADHOC_MATCHING_INVALID_ARG ;
2014-07-31 18:55:42 +00:00
// Multithreading Lock
peerlock . lock ( ) ;
// Find Matching Context
SceNetAdhocMatchingContext * context = findMatchingContext ( matchingId ) ;
// Multithreading Unlock
peerlock . unlock ( ) ;
2014-06-24 16:43:03 +00:00
2014-07-31 18:55:42 +00:00
// Found Context
if ( context ! = NULL )
{
// Running Context
if ( context - > running )
{
// Length Buffer available
2015-01-04 13:09:41 +00:00
if ( sizeAddr ! = 0 )
2014-07-31 18:55:42 +00:00
{
int * buflen = ( int * ) Memory : : GetPointer ( sizeAddr ) ;
SceNetAdhocMatchingMemberInfoEmu * buf2 = NULL ;
if ( Memory : : IsValidAddress ( buf ) ) {
buf2 = ( SceNetAdhocMatchingMemberInfoEmu * ) Memory : : GetPointer ( buf ) ;
}
2014-06-24 16:43:03 +00:00
2014-07-31 18:55:42 +00:00
// Number of Connected Peers
uint32_t peercount = countConnectedPeers ( context ) ;
// Calculate Connected Peer Bytesize
int available = sizeof ( SceNetAdhocMatchingMemberInfoEmu ) * peercount ;
// Length Returner Mode
2015-01-04 13:09:41 +00:00
if ( buf = = 0 )
2014-07-31 18:55:42 +00:00
{
// Get Connected Peer Count
* buflen = available ;
}
// Normal Mode
else
{
// Fix Negative Length
if ( ( * buflen ) < 0 ) * buflen = 0 ;
// Fix Oversize Request
if ( ( * buflen ) > available ) * buflen = available ;
// Clear Memory
memset ( buf2 , 0 , * buflen ) ;
// Calculate Requested Peer Count
int requestedpeers = ( * buflen ) / sizeof ( SceNetAdhocMatchingMemberInfoEmu ) ;
// Filled Request Counter
int filledpeers = 0 ;
// Add Self-Peer
if ( requestedpeers > 0 )
{
// Add Local MAC
buf2 [ filledpeers + + ] . mac_addr = context - > mac ;
// Room for more than local peer
if ( requestedpeers > 1 )
{
// P2P Mode
if ( context - > mode = = PSP_ADHOC_MATCHING_MODE_P2P )
{
// Find P2P Brother
SceNetAdhocMatchingMemberInternal * p2p = findP2P ( context ) ;
// P2P Brother found
if ( p2p ! = NULL )
{
// Add P2P Brother MAC
buf2 [ filledpeers + + ] . mac_addr = p2p - > mac ;
}
}
// Parent or Child Mode
else
{
// Iterate Peer List
SceNetAdhocMatchingMemberInternal * peer = context - > peerlist ; for ( ; peer ! = NULL & & filledpeers < requestedpeers ; peer = peer - > next )
{
// Parent Mode
if ( context - > mode = = PSP_ADHOC_MATCHING_MODE_PARENT )
{
// Interested in Children (Michael Jackson Style)
if ( peer - > state = = PSP_ADHOC_MATCHING_PEER_CHILD )
{
// Add Child MAC
buf2 [ filledpeers + + ] . mac_addr = peer - > mac ;
}
}
// Children Mode
else
{
// Interested in Parent & Siblings
if ( peer - > state = = PSP_ADHOC_MATCHING_PEER_CHILD | | peer - > state = = PSP_ADHOC_MATCHING_PEER_PARENT )
{
// Add Peer MAC
buf2 [ filledpeers + + ] . mac_addr = peer - > mac ;
}
}
}
}
}
// Link Result List
int i = 0 ;
for ( ; i < filledpeers - 1 ; i + + )
{
// Link Next Element
//buf2[i].next = &buf2[i + 1];
buf2 [ i ] . next = buf + ( sizeof ( SceNetAdhocMatchingMemberInfoEmu ) * i ) + sizeof ( SceNetAdhocMatchingMemberInfoEmu ) ;
}
// Fix Last Element
if ( filledpeers > 0 ) buf2 [ filledpeers - 1 ] . next = 0 ;
}
// Fix Buffer Size
* buflen = sizeof ( SceNetAdhocMatchingMemberInfoEmu ) * filledpeers ;
}
// Return Success
return 0 ;
2014-06-24 16:43:03 +00:00
}
2014-07-31 18:55:42 +00:00
// Invalid Arguments
return ERROR_NET_ADHOC_MATCHING_INVALID_ARG ;
}
2014-06-24 16:43:03 +00:00
2014-07-31 18:55:42 +00:00
// Context not running
return ERROR_NET_ADHOC_MATCHING_NOT_RUNNING ;
2014-06-24 16:43:03 +00:00
}
2014-07-31 18:55:42 +00:00
// Invalid Matching ID
return ERROR_NET_ADHOC_MATCHING_INVALID_ID ;
2013-09-07 09:06:06 +00:00
}
2014-07-31 18:55:42 +00:00
int sceNetAdhocMatchingSendData ( int matchingId , const char * mac , int dataLen , u32 dataAddr ) {
WARN_LOG ( SCENET , " UNTESTED sceNetAdhocMatchingSendData(%i, %s, %i, %08x) " , matchingId , mac , dataLen , dataAddr ) ;
2014-05-24 23:57:02 +00:00
if ( ! g_Config . bEnableWlan )
return - 1 ;
2014-07-31 18:55:42 +00:00
// Initialized Library
if ( netAdhocMatchingInited )
{
// Valid Arguments
if ( mac ! = NULL )
{
// Find Matching Context
SceNetAdhocMatchingContext * context = findMatchingContext ( matchingId ) ;
// Found Context
if ( context ! = NULL )
{
// Running Context
if ( context - > running )
{
// Find Target Peer
SceNetAdhocMatchingMemberInternal * peer = findPeer ( context , ( SceNetEtherAddr * ) mac ) ;
// Found Peer
if ( peer ! = NULL )
{
void * data = NULL ;
if ( Memory : : IsValidAddress ( dataAddr ) ) data = Memory : : GetPointer ( dataAddr ) ;
// Valid Data Length
if ( dataLen > 0 & & data ! = NULL )
{
// Valid Peer Connection State
if ( peer - > state = = PSP_ADHOC_MATCHING_PEER_PARENT | | peer - > state = = PSP_ADHOC_MATCHING_PEER_CHILD | | peer - > state = = PSP_ADHOC_MATCHING_PEER_P2P )
{
// Send in Progress
if ( peer - > sending ) return ERROR_NET_ADHOC_MATCHING_DATA_BUSY ;
// Mark Peer as Sending
peer - > sending = 1 ;
// Send Data to Peer
sendBulkData ( context , peer , dataLen , data ) ;
// Return Success
return 0 ;
}
// Not connected / accepted
return ERROR_NET_ADHOC_MATCHING_NOT_ESTABLISHED ;
}
// Invalid Data Length
return ERROR_NET_ADHOC_MATCHING_INVALID_DATALEN ;
}
// Peer not found
return ERROR_NET_ADHOC_MATCHING_UNKNOWN_TARGET ;
}
// Context not running
return ERROR_NET_ADHOC_MATCHING_NOT_RUNNING ;
}
// Invalid Matching ID
return ERROR_NET_ADHOC_MATCHING_INVALID_ID ;
}
// Invalid Arguments
return ERROR_NET_ADHOC_MATCHING_INVALID_ARG ;
}
// Uninitialized Library
return ERROR_NET_ADHOC_MATCHING_NOT_INITIALIZED ;
2013-09-07 09:06:06 +00:00
}
2014-07-31 18:55:42 +00:00
int sceNetAdhocMatchingAbortSendData ( int matchingId , const char * mac ) {
WARN_LOG ( SCENET , " UNTESTED sceNetAdhocMatchingAbortSendData(%i, %s) " , matchingId , mac ) ;
2014-05-24 23:57:02 +00:00
if ( ! g_Config . bEnableWlan )
return - 1 ;
2014-07-31 18:55:42 +00:00
// Initialized Library
if ( netAdhocMatchingInited )
{
// Valid Arguments
if ( mac ! = NULL )
{
// Find Matching Context
SceNetAdhocMatchingContext * context = findMatchingContext ( matchingId ) ;
// Found Context
if ( context ! = NULL )
{
// Running Context
if ( context - > running )
{
// Find Target Peer
SceNetAdhocMatchingMemberInternal * peer = findPeer ( context , ( SceNetEtherAddr * ) mac ) ;
// Found Peer
if ( peer ! = NULL )
{
// Peer is sending
if ( peer - > sending )
{
// Set Peer as Bulk Idle
peer - > sending = 0 ;
// Stop Bulk Data Sending (if in progress)
abortBulkTransfer ( context , peer ) ;
}
// Return Success
return 0 ;
}
// Peer not found
return ERROR_NET_ADHOC_MATCHING_UNKNOWN_TARGET ;
}
// Context not running
return ERROR_NET_ADHOC_MATCHING_NOT_RUNNING ;
}
// Invalid Matching ID
return ERROR_NET_ADHOC_MATCHING_INVALID_ID ;
}
// Invalid Arguments
return ERROR_NET_ADHOC_MATCHING_INVALID_ARG ;
}
// Uninitialized Library
return ERROR_NET_ADHOC_MATCHING_NOT_INITIALIZED ;
2013-09-07 09:06:06 +00:00
}
2014-12-08 09:40:08 +00:00
static int sceNetAdhocMatchingGetPoolMaxAlloc ( ) {
2013-11-28 06:05:11 +00:00
ERROR_LOG ( SCENET , " UNIMPL sceNetAdhocMatchingGetPoolMaxAlloc() " ) ;
2014-05-24 23:57:02 +00:00
if ( ! g_Config . bEnableWlan )
return - 1 ;
2014-07-31 18:55:42 +00:00
// Lazy way out - hardcoded return value
return ( 50 * 1024 ) ;
2013-09-07 09:06:06 +00:00
}
2014-07-31 18:55:42 +00:00
int sceNetAdhocMatchingGetPoolStat ( u32 poolstatPtr ) {
WARN_LOG ( SCENET , " UNTESTED sceNetAdhocMatchingGetPoolStat(%08x) " , poolstatPtr ) ;
2014-05-24 23:57:02 +00:00
if ( ! g_Config . bEnableWlan )
return - 1 ;
2014-07-31 18:55:42 +00:00
// Initialized Library
if ( netAdhocMatchingInited )
{
SceNetMallocStat * poolstat = NULL ;
if ( Memory : : IsValidAddress ( poolstatPtr ) ) poolstat = ( SceNetMallocStat * ) Memory : : GetPointer ( poolstatPtr ) ;
// Valid Argument
if ( poolstat ! = NULL )
{
// Fill Poolstat with Fake Data
poolstat - > pool = fakePoolSize ;
poolstat - > maximum = fakePoolSize / 8 * 6 ;
poolstat - > free = fakePoolSize / 8 * 7 ;
// Return Success
return 0 ;
}
// Invalid Argument
return ERROR_NET_ADHOC_MATCHING_INVALID_ARG ;
}
// Uninitialized Library
return ERROR_NET_ADHOC_MATCHING_NOT_INITIALIZED ;
2013-09-07 09:06:06 +00:00
}
2015-01-04 13:07:44 +00:00
void __NetTriggerCallbacks ( )
{
{
lock_guard adhocGuard ( adhocEvtMtx ) ;
for ( auto & params : adhocctlEvents )
{
int flags = params . first ;
int error = params . second ;
u32_le args [ 3 ] = { 0 , 0 , 0 } ;
args [ 0 ] = flags ;
args [ 1 ] = error ;
for ( std : : map < int , AdhocctlHandler > : : iterator it = adhocctlHandlers . begin ( ) ; it ! = adhocctlHandlers . end ( ) ; + + it ) {
args [ 2 ] = it - > second . argument ;
__KernelDirectMipsCall ( it - > second . entryPoint , NULL , args , 3 , true ) ;
}
}
adhocctlEvents . clear ( ) ;
for ( auto & param : matchingEvents )
{
u32_le * args = ( u32_le * ) param ;
AfterMatchingMipsCall * after = ( AfterMatchingMipsCall * ) __KernelCreateAction ( actionAfterMatchingMipsCall ) ;
after - > SetContextID ( args [ 0 ] , args [ 1 ] ) ;
__KernelDirectMipsCall ( args [ 5 ] , after , args , 5 , true ) ;
}
matchingEvents . clear ( ) ;
}
//magically make this work
hleDelayResult ( 0 , " Prevent Adhoc thread from blocking " , 1000 ) ;
}
2013-09-06 22:55:42 +00:00
const HLEFunction sceNetAdhoc [ ] = {
2015-03-22 23:57:56 +00:00
{ 0XE1D621D7 , & WrapU_V < sceNetAdhocInit > , " sceNetAdhocInit " , ' x ' , " " } ,
{ 0XA62C6F57 , & WrapI_V < sceNetAdhocTerm > , " sceNetAdhocTerm " , ' i ' , " " } ,
{ 0X0AD043ED , & WrapI_U < sceNetAdhocctlConnect > , " sceNetAdhocctlConnect " , ' i ' , " x " } ,
{ 0X6F92741B , & WrapI_CUIU < sceNetAdhocPdpCreate > , " sceNetAdhocPdpCreate " , ' i ' , " sxix " } ,
{ 0XABED3790 , & WrapI_ICUVIII < sceNetAdhocPdpSend > , " sceNetAdhocPdpSend " , ' i ' , " isxpiii " } ,
{ 0XDFE53E03 , & WrapI_IVVVVUI < sceNetAdhocPdpRecv > , " sceNetAdhocPdpRecv " , ' i ' , " ippppxi " } ,
{ 0X7F27BB5E , & WrapI_II < sceNetAdhocPdpDelete > , " sceNetAdhocPdpDelete " , ' i ' , " ii " } ,
{ 0XC7C1FC57 , & WrapI_UU < sceNetAdhocGetPdpStat > , " sceNetAdhocGetPdpStat " , ' i ' , " xx " } ,
{ 0X157E6225 , & WrapI_II < sceNetAdhocPtpClose > , " sceNetAdhocPtpClose " , ' i ' , " ii " } ,
{ 0X4DA4C788 , & WrapI_IUUII < sceNetAdhocPtpSend > , " sceNetAdhocPtpSend " , ' i ' , " ixxii " } ,
{ 0X877F6D66 , & WrapI_CICIIIII < sceNetAdhocPtpOpen > , " sceNetAdhocPtpOpen " , ' i ' , " sisiiiii " } ,
{ 0X8BEA2B3E , & WrapI_IUUII < sceNetAdhocPtpRecv > , " sceNetAdhocPtpRecv " , ' i ' , " ixxii " } ,
{ 0X9DF81198 , & WrapI_IUUII < sceNetAdhocPtpAccept > , " sceNetAdhocPtpAccept " , ' i ' , " ixxii " } ,
{ 0XE08BDAC1 , & WrapI_CIIIIII < sceNetAdhocPtpListen > , " sceNetAdhocPtpListen " , ' i ' , " siiiiii " } ,
{ 0XFC6FC07B , & WrapI_III < sceNetAdhocPtpConnect > , " sceNetAdhocPtpConnect " , ' i ' , " iii " } ,
{ 0X9AC2EEAC , & WrapI_III < sceNetAdhocPtpFlush > , " sceNetAdhocPtpFlush " , ' i ' , " iii " } ,
{ 0XB9685118 , & WrapI_UU < sceNetAdhocGetPtpStat > , " sceNetAdhocGetPtpStat " , ' i ' , " xx " } ,
{ 0X3278AB0C , & WrapI_CUI < sceNetAdhocGameModeCreateReplica > , " sceNetAdhocGameModeCreateReplica " , ' i ' , " sxi " } ,
{ 0X98C204C8 , & WrapI_V < sceNetAdhocGameModeUpdateMaster > , " sceNetAdhocGameModeUpdateMaster " , ' i ' , " " } ,
{ 0XFA324B4E , & WrapI_IU < sceNetAdhocGameModeUpdateReplica > , " sceNetAdhocGameModeUpdateReplica " , ' i ' , " ix " } ,
{ 0XA0229362 , & WrapI_V < sceNetAdhocGameModeDeleteMaster > , " sceNetAdhocGameModeDeleteMaster " , ' i ' , " " } ,
{ 0X0B2228E9 , & WrapI_I < sceNetAdhocGameModeDeleteReplica > , " sceNetAdhocGameModeDeleteReplica " , ' i ' , " i " } ,
{ 0X7F75C338 , & WrapI_UI < sceNetAdhocGameModeCreateMaster > , " sceNetAdhocGameModeCreateMaster " , ' i ' , " xi " } ,
{ 0X73BFD52D , & WrapI_II < sceNetAdhocSetSocketAlert > , " sceNetAdhocSetSocketAlert " , ' i ' , " ii " } ,
{ 0X4D2CE199 , & WrapI_IU < sceNetAdhocGetSocketAlert > , " sceNetAdhocGetSocketAlert " , ' i ' , " ix " } ,
{ 0X7A662D6B , & WrapI_UIII < sceNetAdhocPollSocket > , " sceNetAdhocPollSocket " , ' i ' , " xiii " } ,
2015-01-04 13:07:44 +00:00
// Fake function for PPSSPP's use.
2015-03-22 23:57:56 +00:00
{ 0X756E6E6F , & WrapV_V < __NetTriggerCallbacks > , " __NetTriggerCallbacks " , ' v ' , " " } ,
2013-09-06 22:55:42 +00:00
} ;
const HLEFunction sceNetAdhocMatching [ ] = {
2015-03-22 23:57:56 +00:00
{ 0X2A2A1E07 , & WrapI_U < sceNetAdhocMatchingInit > , " sceNetAdhocMatchingInit " , ' i ' , " x " } ,
{ 0X7945ECDA , & WrapI_V < sceNetAdhocMatchingTerm > , " sceNetAdhocMatchingTerm " , ' i ' , " " } ,
{ 0XCA5EDA6F , & WrapI_IIIIIIIIU < sceNetAdhocMatchingCreate > , " sceNetAdhocMatchingCreate " , ' i ' , " iiiiiiiix " } ,
{ 0X93EF3843 , & WrapI_IIIIIIU < sceNetAdhocMatchingStart > , " sceNetAdhocMatchingStart " , ' i ' , " iiiiiix " } ,
{ 0X32B156B3 , & WrapI_I < sceNetAdhocMatchingStop > , " sceNetAdhocMatchingStop " , ' i ' , " i " } ,
{ 0XF16EAF4F , & WrapI_I < sceNetAdhocMatchingDelete > , " sceNetAdhocMatchingDelete " , ' i ' , " i " } ,
{ 0X5E3D4B79 , & WrapI_ICIU < sceNetAdhocMatchingSelectTarget > , " sceNetAdhocMatchingSelectTarget " , ' i ' , " isix " } ,
{ 0XEA3C6108 , & WrapI_IC < sceNetAdhocMatchingCancelTarget > , " sceNetAdhocMatchingCancelTarget " , ' i ' , " is " } ,
{ 0X8F58BEDF , & WrapI_ICIU < sceNetAdhocMatchingCancelTargetWithOpt > , " sceNetAdhocMatchingCancelTargetWithOpt " , ' i ' , " isix " } ,
{ 0XB5D96C2A , & WrapI_IUU < sceNetAdhocMatchingGetHelloOpt > , " sceNetAdhocMatchingGetHelloOpt " , ' i ' , " ixx " } ,
{ 0XB58E61B7 , & WrapI_IIU < sceNetAdhocMatchingSetHelloOpt > , " sceNetAdhocMatchingSetHelloOpt " , ' i ' , " iix " } ,
{ 0XC58BCD9E , & WrapI_IUU < sceNetAdhocMatchingGetMembers > , " sceNetAdhocMatchingGetMembers " , ' i ' , " ixx " } ,
{ 0XF79472D7 , & WrapI_ICIU < sceNetAdhocMatchingSendData > , " sceNetAdhocMatchingSendData " , ' i ' , " isix " } ,
{ 0XEC19337D , & WrapI_IC < sceNetAdhocMatchingAbortSendData > , " sceNetAdhocMatchingAbortSendData " , ' i ' , " is " } ,
{ 0X40F8F435 , & WrapI_V < sceNetAdhocMatchingGetPoolMaxAlloc > , " sceNetAdhocMatchingGetPoolMaxAlloc " , ' i ' , " " } ,
{ 0X9C5CFB7D , & WrapI_U < sceNetAdhocMatchingGetPoolStat > , " sceNetAdhocMatchingGetPoolStat " , ' i ' , " x " } ,
2013-09-06 22:55:42 +00:00
} ;
2014-12-08 09:40:08 +00:00
static int sceNetAdhocctlExitGameMode ( ) {
2013-11-28 06:05:11 +00:00
ERROR_LOG ( SCENET , " UNIMPL sceNetAdhocctlExitGameMode() " ) ;
2014-07-31 18:55:42 +00:00
return 0 ;
2013-09-07 09:06:06 +00:00
}
2014-12-08 09:40:08 +00:00
static int sceNetAdhocctlGetGameModeInfo ( u32 infoAddr ) {
2013-11-28 06:05:11 +00:00
ERROR_LOG ( SCENET , " UNIMPL sceNetAdhocctlGetGameModeInfo(%08x) " , infoAddr ) ;
return - 1 ;
2013-09-07 09:06:06 +00:00
}
2014-12-08 09:40:08 +00:00
static int sceNetAdhocctlGetPeerList ( u32 sizeAddr , u32 bufAddr ) {
2014-07-31 18:55:42 +00:00
s32_le * buflen = NULL ;
if ( Memory : : IsValidAddress ( sizeAddr ) ) buflen = ( s32_le * ) Memory : : GetPointer ( sizeAddr ) ;
SceNetAdhocctlPeerInfoEmu * buf = NULL ;
if ( Memory : : IsValidAddress ( bufAddr ) ) buf = ( SceNetAdhocctlPeerInfoEmu * ) Memory : : GetPointer ( bufAddr ) ;
DEBUG_LOG ( SCENET , " sceNetAdhocctlGetPeerList([%08x]=%i, %08x) at %08x " , sizeAddr , buflen ? * buflen : - 1 , bufAddr , currentMIPS - > pc ) ;
2013-12-04 10:07:00 +00:00
if ( ! g_Config . bEnableWlan ) {
return - 1 ;
}
2013-11-28 06:05:11 +00:00
// Initialized Library
2013-12-05 19:43:30 +00:00
if ( netAdhocctlInited ) {
2013-11-28 06:05:11 +00:00
// Minimum Arguments
2013-12-05 19:43:30 +00:00
if ( buflen ! = NULL ) {
2013-11-28 06:05:11 +00:00
// Multithreading Lock
peerlock . lock ( ) ;
// Length Calculation Mode
2013-12-05 19:43:30 +00:00
if ( buf = = NULL ) * buflen = getActivePeerCount ( ) * sizeof ( SceNetAdhocctlPeerInfoEmu ) ;
2013-11-28 06:05:11 +00:00
// Normal Mode
else {
// Discovery Counter
int discovered = 0 ;
// Calculate Request Count
int requestcount = * buflen / sizeof ( SceNetAdhocctlPeerInfoEmu ) ;
// Clear Memory
memset ( buf , 0 , * buflen ) ;
// Minimum Arguments
2013-12-05 19:43:30 +00:00
if ( requestcount > 0 ) {
2013-11-28 06:05:11 +00:00
// Peer Reference
SceNetAdhocctlPeerInfo * peer = friends ;
// Iterate Peers
2013-12-05 19:43:30 +00:00
for ( ; peer ! = NULL & & discovered < requestcount ; peer = peer - > next ) {
2013-11-28 06:05:11 +00:00
// Fake Receive Time
2014-07-31 18:55:42 +00:00
if ( peer - > last_recv ! = 0 ) peer - > last_recv = CoreTiming : : GetGlobalTimeUsScaled ( ) ;
2013-11-28 06:05:11 +00:00
// Copy Peer Info
buf [ discovered ] . nickname = peer - > nickname ;
buf [ discovered ] . mac_addr = peer - > mac_addr ;
buf [ discovered ] . ip_addr = peer - > ip_addr ;
buf [ discovered ] . last_recv = peer - > last_recv ;
discovered + + ;
}
// Link List
2013-12-05 19:43:30 +00:00
int i = 0 ; for ( ; i < discovered - 1 ; i + + ) {
2013-11-28 06:05:11 +00:00
// Link Network
2014-07-31 18:55:42 +00:00
buf [ i ] . next = bufAddr + ( sizeof ( SceNetAdhocctlPeerInfoEmu ) * i ) + sizeof ( SceNetAdhocctlPeerInfoEmu ) ;
2013-11-28 06:05:11 +00:00
}
// Fix Last Element
2013-12-05 19:43:30 +00:00
if ( discovered > 0 ) buf [ discovered - 1 ] . next = 0 ;
2013-11-28 06:05:11 +00:00
}
// Fix Size
2014-07-31 18:55:42 +00:00
* buflen = discovered * sizeof ( SceNetAdhocctlPeerInfoEmu ) ;
2013-11-28 06:05:11 +00:00
}
// Multithreading Unlock
peerlock . unlock ( ) ;
// Return Success
return 0 ;
}
// Invalid Arguments
return ERROR_NET_ADHOCCTL_INVALID_ARG ;
}
// Uninitialized Library
return ERROR_NET_ADHOCCTL_NOT_INITIALIZED ;
2013-09-07 09:06:06 +00:00
}
2014-12-08 09:40:08 +00:00
static int sceNetAdhocctlGetAddrByName ( const char * nickName , u32 sizeAddr , u32 bufAddr ) {
2014-07-31 18:55:42 +00:00
s32_le * buflen = NULL ; //int32_t
if ( Memory : : IsValidAddress ( sizeAddr ) ) buflen = ( s32_le * ) Memory : : GetPointer ( sizeAddr ) ;
WARN_LOG ( SCENET , " UNTESTED sceNetAdhocctlGetPeerList(%s, [%08x]=%i, %08x) " , nickName , sizeAddr , buflen ? * buflen : - 1 , bufAddr ) ;
// Library initialized
if ( netAdhocctlInited )
{
// Valid Arguments
if ( nickName ! = NULL & & buflen ! = NULL )
{
SceNetAdhocctlPeerInfoEmu * buf = NULL ;
if ( Memory : : IsValidAddress ( bufAddr ) ) buf = ( SceNetAdhocctlPeerInfoEmu * ) Memory : : GetPointer ( bufAddr ) ;
// Multithreading Lock
peerlock . lock ( ) ;
// Length Calculation Mode
if ( buf = = NULL ) * buflen = getNicknameCount ( nickName ) * sizeof ( SceNetAdhocctlPeerInfoEmu ) ;
// Normal Information Mode
else
{
// Clear Memory
memset ( buf , 0 , * buflen ) ;
// Discovered Player Count
int discovered = 0 ;
// Calculate Requested Elements
int requestcount = * buflen / sizeof ( SceNetAdhocctlPeerInfoEmu ) ;
// Minimum Space available
if ( requestcount > 0 )
{
// Local Nickname Matches
if ( strcmp ( ( char * ) parameter . nickname . data , nickName ) = = 0 )
{
// Get Local IP Address
sockaddr_in addr ;
getLocalIp ( & addr ) ;
//buf->next = 0;
buf [ discovered ] . nickname = parameter . nickname ;
buf [ discovered ] . nickname . data [ ADHOCCTL_NICKNAME_LEN - 1 ] = 0 ; // last char need to be null-terminated char
getLocalMac ( & buf [ discovered ] . mac_addr ) ;
buf [ discovered ] . ip_addr = addr . sin_addr . s_addr ; // 0x11111111;
//buf->padding = 0x1111; //0;
buf [ discovered + + ] . last_recv = CoreTiming : : GetGlobalTimeUsScaled ( ) ;
}
// Peer Reference
SceNetAdhocctlPeerInfo * peer = friends ;
// Iterate Peers
for ( ; peer ! = NULL & & discovered < requestcount ; peer = peer - > next )
{
// Match found
if ( strcmp ( ( char * ) peer - > nickname . data , nickName ) = = 0 )
{
// Fake Receive Time
if ( peer - > last_recv ! = 0 ) peer - > last_recv = CoreTiming : : GetGlobalTimeUsScaled ( ) ; //sceKernelGetSystemTimeWide();
// Copy Peer Info
buf [ discovered ] . nickname = peer - > nickname ;
buf [ discovered ] . nickname . data [ ADHOCCTL_NICKNAME_LEN - 1 ] = 0 ; // last char need to be null-terminated char
buf [ discovered ] . mac_addr = peer - > mac_addr ;
buf [ discovered ] . ip_addr = peer - > ip_addr ;
buf [ discovered + + ] . last_recv = peer - > last_recv ;
}
}
// Link List
int i = 0 ; for ( ; i < discovered - 1 ; i + + )
{
// Link Network
buf [ i ] . next = bufAddr + ( sizeof ( SceNetAdhocctlPeerInfoEmu ) * i ) + sizeof ( SceNetAdhocctlPeerInfoEmu ) ;
}
// Fix Last Element
if ( discovered > 0 ) buf [ discovered - 1 ] . next = 0 ;
}
// Fix Buffer Size
* buflen = discovered * sizeof ( SceNetAdhocctlPeerInfoEmu ) ;
}
// Multithreading Unlock
peerlock . unlock ( ) ;
// Return Success
return 0 ;
}
// Invalid Arguments
return ERROR_NET_ADHOCCTL_INVALID_ARG ;
}
// Library uninitialized
return ERROR_NET_ADHOCCTL_NOT_INITIALIZED ;
2013-09-07 09:06:06 +00:00
}
2013-09-06 22:55:42 +00:00
const HLEFunction sceNetAdhocctl [ ] = {
2015-03-22 23:57:56 +00:00
{ 0XE26F226E , & WrapU_IIU < sceNetAdhocctlInit > , " sceNetAdhocctlInit " , ' x ' , " iix " } ,
{ 0X9D689E13 , & WrapI_V < sceNetAdhocctlTerm > , " sceNetAdhocctlTerm " , ' i ' , " " } ,
{ 0X20B317A0 , & WrapU_UU < sceNetAdhocctlAddHandler > , " sceNetAdhocctlAddHandler " , ' x ' , " xx " } ,
{ 0X6402490B , & WrapU_U < sceNetAdhocctlDelHandler > , " sceNetAdhocctlDelHandler " , ' x ' , " x " } ,
{ 0X34401D65 , & WrapU_V < sceNetAdhocctlDisconnect > , " sceNetAdhocctlDisconnect " , ' x ' , " " } ,
{ 0X0AD043ED , & WrapI_U < sceNetAdhocctlConnect > , " sceNetAdhocctlConnect " , ' i ' , " x " } ,
{ 0X08FFF7A0 , & WrapI_V < sceNetAdhocctlScan > , " sceNetAdhocctlScan " , ' i ' , " " } ,
{ 0X75ECD386 , & WrapI_U < sceNetAdhocctlGetState > , " sceNetAdhocctlGetState " , ' i ' , " x " } ,
{ 0X8916C003 , & WrapI_CU < sceNetAdhocctlGetNameByAddr > , " sceNetAdhocctlGetNameByAddr " , ' i ' , " sx " } ,
{ 0XDED9D28E , & WrapI_U < sceNetAdhocctlGetParameter > , " sceNetAdhocctlGetParameter " , ' i ' , " x " } ,
{ 0X81AEE1BE , & WrapI_UU < sceNetAdhocctlGetScanInfo > , " sceNetAdhocctlGetScanInfo " , ' i ' , " xx " } ,
{ 0X5E7F79C9 , & WrapI_U < sceNetAdhocctlJoin > , " sceNetAdhocctlJoin " , ' i ' , " x " } ,
{ 0X8DB83FDC , & WrapI_CIU < sceNetAdhocctlGetPeerInfo > , " sceNetAdhocctlGetPeerInfo " , ' i ' , " six " } ,
{ 0XEC0635C1 , & WrapI_C < sceNetAdhocctlCreate > , " sceNetAdhocctlCreate " , ' i ' , " s " } ,
{ 0XA5C055CE , & WrapI_CIIUII < sceNetAdhocctlCreateEnterGameMode > , " sceNetAdhocctlCreateEnterGameMode " , ' i ' , " siixii " } ,
{ 0X1FF89745 , & WrapI_CCII < sceNetAdhocctlJoinEnterGameMode > , " sceNetAdhocctlJoinEnterGameMode " , ' i ' , " ssii " } ,
{ 0XCF8E084D , & WrapI_V < sceNetAdhocctlExitGameMode > , " sceNetAdhocctlExitGameMode " , ' i ' , " " } ,
{ 0XE162CB14 , & WrapI_UU < sceNetAdhocctlGetPeerList > , " sceNetAdhocctlGetPeerList " , ' i ' , " xx " } ,
{ 0X362CBE8F , & WrapI_U < sceNetAdhocctlGetAdhocId > , " sceNetAdhocctlGetAdhocId " , ' i ' , " x " } ,
{ 0X5A014CE0 , & WrapI_U < sceNetAdhocctlGetGameModeInfo > , " sceNetAdhocctlGetGameModeInfo " , ' i ' , " x " } ,
{ 0X99560ABE , & WrapI_CUU < sceNetAdhocctlGetAddrByName > , " sceNetAdhocctlGetAddrByName " , ' i ' , " sxx " } ,
{ 0XB0B80E80 , & WrapI_CIIIUUI < sceNetAdhocctlCreateEnterGameModeMin > , " sceNetAdhocctlCreateEnterGameModeMin " , ' i ' , " siiixxi " } , // ??
2013-09-06 22:55:42 +00:00
} ;
2014-07-31 18:55:42 +00:00
int sceNetAdhocDiscoverInitStart ( ) {
ERROR_LOG ( SCENET , " UNIMPL sceNetAdhocDiscoverInitStart() " ) ;
return 0 ;
}
int sceNetAdhocDiscoverStop ( ) {
ERROR_LOG ( SCENET , " UNIMPL sceNetAdhocDiscoverStop() " ) ;
return 0 ;
}
int sceNetAdhocDiscoverTerm ( ) {
ERROR_LOG ( SCENET , " UNIMPL sceNetAdhocDiscoverTerm() " ) ;
return 0 ;
}
int sceNetAdhocDiscoverUpdate ( ) {
ERROR_LOG ( SCENET , " UNIMPL sceNetAdhocDiscoverUpdate() " ) ;
return 0 ;
}
int sceNetAdhocDiscoverGetStatus ( ) {
ERROR_LOG ( SCENET , " UNIMPL sceNetAdhocDiscoverGetStatus() " ) ;
return 0 ;
}
int sceNetAdhocDiscoverRequestSuspend ( void )
{
ERROR_LOG ( SCENET , " UNIMPL sceNetAdhocDiscoverRequestSuspend() " ) ;
return 0 ;
}
2013-09-06 22:55:42 +00:00
const HLEFunction sceNetAdhocDiscover [ ] = {
2015-03-22 23:57:56 +00:00
{ 0X941B3877 , & WrapI_V < sceNetAdhocDiscoverInitStart > , " sceNetAdhocDiscoverInitStart " , ' i ' , " " } ,
{ 0X52DE1B97 , & WrapI_V < sceNetAdhocDiscoverUpdate > , " sceNetAdhocDiscoverUpdate " , ' i ' , " " } ,
{ 0X944DDBC6 , & WrapI_V < sceNetAdhocDiscoverGetStatus > , " sceNetAdhocDiscoverGetStatus " , ' i ' , " " } ,
{ 0XA2246614 , & WrapI_V < sceNetAdhocDiscoverTerm > , " sceNetAdhocDiscoverTerm " , ' i ' , " " } ,
{ 0XF7D13214 , & WrapI_V < sceNetAdhocDiscoverStop > , " sceNetAdhocDiscoverStop " , ' i ' , " " } ,
{ 0XA423A21B , & WrapI_V < sceNetAdhocDiscoverRequestSuspend > , " sceNetAdhocDiscoverRequestSuspend " , ' i ' , " " } ,
2013-09-06 22:55:42 +00:00
} ;
void Register_sceNetAdhoc ( ) {
2013-11-28 06:05:11 +00:00
RegisterModule ( " sceNetAdhoc " , ARRAY_SIZE ( sceNetAdhoc ) , sceNetAdhoc ) ;
RegisterModule ( " sceNetAdhocMatching " , ARRAY_SIZE ( sceNetAdhocMatching ) , sceNetAdhocMatching ) ;
RegisterModule ( " sceNetAdhocDiscover " , ARRAY_SIZE ( sceNetAdhocDiscover ) , sceNetAdhocDiscover ) ;
RegisterModule ( " sceNetAdhocctl " , ARRAY_SIZE ( sceNetAdhocctl ) , sceNetAdhocctl ) ;
2013-09-06 22:55:42 +00:00
}
2014-07-31 18:55:42 +00:00
/**
* Broadcast Ping Message to other Matching Users
* @ param context Matching Context Pointer
*/
void broadcastPingMessage ( SceNetAdhocMatchingContext * context )
{
// Ping Opcode
uint8_t ping = PSP_ADHOC_MATCHING_PACKET_PING ;
// Send Broadcast
context - > socketlock - > lock ( ) ;
sceNetAdhocPdpSend ( context - > socket , ( const char * ) ( SceNetEtherAddr * ) broadcastMAC , context - > port , & ping , sizeof ( ping ) , 0 , ADHOC_F_NONBLOCK ) ;
context - > socketlock - > unlock ( ) ;
}
/**
* Broadcast Hello Message to other Matching Users
* @ param context Matching Context Pointer
*/
void broadcastHelloMessage ( SceNetAdhocMatchingContext * context )
{
static uint8_t * hello = NULL ;
static int32_t len = - 5 ;
// Allocate Hello Message Buffer, reuse when necessary
if ( ( int32_t ) context - > hellolen > len ) {
hello = ( uint8_t * ) realloc ( hello , 5 + context - > hellolen ) ;
len = context - > hellolen ;
}
// Allocated Hello Message Buffer
if ( hello ! = NULL )
{
// Hello Opcode
hello [ 0 ] = PSP_ADHOC_MATCHING_PACKET_HELLO ;
// Hello Data Length (have to memcpy this to avoid cpu alignment crash)
memcpy ( hello + 1 , & context - > hellolen , sizeof ( context - > hellolen ) ) ;
// Copy Hello Data
if ( context - > hellolen > 0 ) memcpy ( hello + 5 , context - > hello , context - > hellolen ) ;
// Send Broadcast
context - > socketlock - > lock ( ) ;
sceNetAdhocPdpSend ( context - > socket , ( const char * ) ( SceNetEtherAddr * ) broadcastMAC , context - > port , hello , 5 + context - > hellolen , 0 , ADHOC_F_NONBLOCK ) ;
context - > socketlock - > unlock ( ) ;
// Free Memory, not needed since it may be reused again later
//free(hello);
}
}
/**
* Send Accept Packet to Player
* @ param context Matching Context Pointer
* @ param mac Target Player MAC
* @ param optlen Optional Data Length
* @ param opt Optional Data
*/
void sendAcceptPacket ( SceNetAdhocMatchingContext * context , SceNetEtherAddr * mac , int optlen , void * opt )
{
// Find Peer
SceNetAdhocMatchingMemberInternal * peer = findPeer ( context , mac ) ;
// Found Peer
if ( peer ! = NULL & & ( peer - > state = = PSP_ADHOC_MATCHING_PEER_CHILD | | peer - > state = = PSP_ADHOC_MATCHING_PEER_P2P ) )
{
// Required Sibling Buffer
uint32_t siblingbuflen = 0 ;
// Parent Mode
if ( context - > mode = = PSP_ADHOC_MATCHING_MODE_PARENT ) siblingbuflen = sizeof ( SceNetEtherAddr ) * ( countConnectedPeers ( context ) - 2 ) ;
// Sibling Count
int siblingcount = siblingbuflen / sizeof ( SceNetEtherAddr ) ;
// Allocate Accept Message Buffer
uint8_t * accept = ( uint8_t * ) malloc ( 9 + optlen + siblingbuflen ) ;
// Allocated Accept Message Buffer
if ( accept ! = NULL )
{
// Accept Opcode
accept [ 0 ] = PSP_ADHOC_MATCHING_PACKET_ACCEPT ;
// Optional Data Length
memcpy ( accept + 1 , & optlen , sizeof ( optlen ) ) ;
// Sibling Count
memcpy ( accept + 5 , & siblingcount , sizeof ( siblingcount ) ) ;
// Copy Optional Data
if ( optlen > 0 ) memcpy ( accept + 9 , opt , optlen ) ;
// Parent Mode Extra Data required
if ( context - > mode = = PSP_ADHOC_MATCHING_MODE_PARENT & & siblingcount > 0 )
{
// Create MAC Array Pointer
uint8_t * siblingmacs = ( uint8_t * ) ( accept + 9 + optlen ) ;
// MAC Writing Pointer
int i = 0 ;
// Iterate Peer List
SceNetAdhocMatchingMemberInternal * item = context - > peerlist ; for ( ; item ! = NULL ; item = item - > next )
{
// Ignore Target
if ( item = = peer ) continue ;
// Copy Child MAC
if ( item - > state = = PSP_ADHOC_MATCHING_PEER_CHILD )
{
// Clone MAC the stupid memcpy way to shut up PSP CPU
memcpy ( siblingmacs + sizeof ( SceNetEtherAddr ) * i + + , & item - > mac , sizeof ( SceNetEtherAddr ) ) ;
}
}
}
// Send Data
context - > socketlock - > lock ( ) ;
sceNetAdhocPdpSend ( context - > socket , ( const char * ) mac , context - > port , accept , 9 + optlen + siblingbuflen , 0 , ADHOC_F_NONBLOCK ) ;
context - > socketlock - > unlock ( ) ;
// Free Memory
free ( accept ) ;
// Spawn Local Established Event
spawnLocalEvent ( context , PSP_ADHOC_MATCHING_EVENT_ESTABLISHED , mac , 0 , NULL ) ;
}
}
}
/**
* Send Join Packet to Player
* @ param context Matching Context Pointer
* @ param mac Target Player MAC
* @ param optlen Optional Data Length
* @ param opt Optional Data
*/
void sendJoinPacket ( SceNetAdhocMatchingContext * context , SceNetEtherAddr * mac , int optlen , void * opt )
{
// Find Peer
SceNetAdhocMatchingMemberInternal * peer = findPeer ( context , mac ) ;
// Valid Peer
if ( peer ! = NULL & & peer - > state = = PSP_ADHOC_MATCHING_PEER_OUTGOING_REQUEST )
{
// Allocate Join Message Buffer
uint8_t * join = ( uint8_t * ) malloc ( 5 + optlen ) ;
// Allocated Join Message Buffer
if ( join ! = NULL )
{
// Join Opcode
join [ 0 ] = PSP_ADHOC_MATCHING_PACKET_JOIN ;
// Optional Data Length
memcpy ( join + 1 , & optlen , sizeof ( optlen ) ) ;
// Copy Optional Data
if ( optlen > 0 ) memcpy ( join + 5 , opt , optlen ) ;
// Send Data
context - > socketlock - > lock ( ) ;
sceNetAdhocPdpSend ( context - > socket , ( const char * ) mac , context - > port , join , 5 + optlen , 0 , ADHOC_F_NONBLOCK ) ;
context - > socketlock - > unlock ( ) ;
// Free Memory
free ( join ) ;
}
}
}
/**
* Send Cancel Packet to Player
* @ param context Matching Context Pointer
* @ param mac Target Player MAC
* @ param optlen Optional Data Length
* @ param opt Optional Data
*/
void sendCancelPacket ( SceNetAdhocMatchingContext * context , SceNetEtherAddr * mac , int optlen , void * opt )
{
// Allocate Cancel Message Buffer
uint8_t * cancel = ( uint8_t * ) malloc ( 5 + optlen ) ;
// Allocated Cancel Message Buffer
if ( cancel ! = NULL )
{
// Cancel Opcode
cancel [ 0 ] = PSP_ADHOC_MATCHING_PACKET_CANCEL ;
// Optional Data Length
memcpy ( cancel + 1 , & optlen , sizeof ( optlen ) ) ;
// Copy Optional Data
if ( optlen > 0 ) memcpy ( cancel + 5 , opt , optlen ) ;
// Send Data
context - > socketlock - > lock ( ) ;
sceNetAdhocPdpSend ( context - > socket , ( const char * ) mac , context - > port , cancel , 5 + optlen , 0 , ADHOC_F_NONBLOCK ) ;
context - > socketlock - > unlock ( ) ;
// Free Memory
free ( cancel ) ;
}
peerlock . lock ( ) ;
// Find Peer
SceNetAdhocMatchingMemberInternal * peer = findPeer ( context , mac ) ;
// Found Peer
if ( peer ! = NULL )
{
// Child Mode Fallback - Delete All
if ( context - > mode = = PSP_ADHOC_MATCHING_MODE_CHILD )
{
// Delete Peer List
clearPeerList ( context ) ;
}
// Delete Peer
else deletePeer ( context , peer ) ;
}
peerlock . unlock ( ) ;
}
/**
* Send Bulk Data Packet to Player
* @ param context Matching Context Pointer
* @ param mac Target Player MAC
* @ param datalen Data Length
* @ param data Data
*/
void sendBulkDataPacket ( SceNetAdhocMatchingContext * context , SceNetEtherAddr * mac , int datalen , void * data )
{
// Find Peer
SceNetAdhocMatchingMemberInternal * peer = findPeer ( context , mac ) ;
// Valid Peer (rest is already checked in send.c)
if ( peer ! = NULL )
{
// Don't send if it's aborted
//if (peer->sending == 0) return;
// Allocate Send Message Buffer
uint8_t * send = ( uint8_t * ) malloc ( 5 + datalen ) ;
// Allocated Send Message Buffer
if ( send ! = NULL )
{
// Send Opcode
send [ 0 ] = PSP_ADHOC_MATCHING_PACKET_BULK ;
// Data Length
memcpy ( send + 1 , & datalen , sizeof ( datalen ) ) ;
// Copy Data
memcpy ( send + 5 , data , datalen ) ;
// Send Data
context - > socketlock - > lock ( ) ;
sceNetAdhocPdpSend ( context - > socket , ( const char * ) mac , context - > port , send , 5 + datalen , 0 , ADHOC_F_NONBLOCK ) ;
context - > socketlock - > unlock ( ) ;
// Free Memory
free ( send ) ;
// Remove Busy Bit from Peer
peer - > sending = 0 ;
// Spawn Data Event
spawnLocalEvent ( context , PSP_ADHOC_MATCHING_EVENT_DATA_ACK , mac , 0 , NULL ) ;
}
}
}
/**
* Tell Established Peers of new Child
* @ param context Matching Context Pointer
* @ param mac New Child ' s MAC
*/
void sendBirthPacket ( SceNetAdhocMatchingContext * context , SceNetEtherAddr * mac )
{
// Find Newborn Child
SceNetAdhocMatchingMemberInternal * newborn = findPeer ( context , mac ) ;
// Found Newborn Child
if ( newborn ! = NULL )
{
// Packet Buffer
uint8_t packet [ 7 ] ;
// Set Opcode
packet [ 0 ] = PSP_ADHOC_MATCHING_PACKET_BIRTH ;
// Set Newborn MAC
memcpy ( packet + 1 , mac , sizeof ( SceNetEtherAddr ) ) ;
// Iterate Peers
SceNetAdhocMatchingMemberInternal * peer = context - > peerlist ; for ( ; peer ! = NULL ; peer = peer - > next )
{
// Skip Newborn Child
if ( peer = = newborn ) continue ;
// Send only to children
if ( peer - > state = = PSP_ADHOC_MATCHING_PEER_CHILD )
{
// Send Packet
context - > socketlock - > lock ( ) ;
int sent = sceNetAdhocPdpSend ( context - > socket , ( const char * ) & peer - > mac , context - > port , packet , sizeof ( packet ) , 0 , ADHOC_F_NONBLOCK ) ;
context - > socketlock - > unlock ( ) ;
// Log Send Success
if ( sent > = 0 )
INFO_LOG ( SCENET , " InputLoop: Sending BIRTH to %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 ] ) ;
else
WARN_LOG ( SCENET , " InputLoop: Failed to Send BIRTH to %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 ] ) ;
}
}
}
}
/**
* Tell Established Peers of abandoned Child
* @ param context Matching Context Pointer
* @ param mac Dead Child ' s MAC
*/
void sendDeathPacket ( SceNetAdhocMatchingContext * context , SceNetEtherAddr * mac )
{
// Find abandoned Child
SceNetAdhocMatchingMemberInternal * deadkid = findPeer ( context , mac ) ;
// Found abandoned Child
if ( deadkid ! = NULL )
{
// Packet Buffer
uint8_t packet [ 7 ] ;
// Set Opcode
packet [ 0 ] = PSP_ADHOC_MATCHING_PACKET_DEATH ;
// Set abandoned Child MAC
memcpy ( packet + 1 , mac , sizeof ( SceNetEtherAddr ) ) ;
// Iterate Peers
SceNetAdhocMatchingMemberInternal * peer = context - > peerlist ; for ( ; peer ! = NULL ; peer = peer - > next )
{
// Skip dead Child
if ( peer = = deadkid ) continue ;
// Send only to children
if ( peer - > state = = PSP_ADHOC_MATCHING_PEER_CHILD )
{
// Send Packet
context - > socketlock - > lock ( ) ;
sceNetAdhocPdpSend ( context - > socket , ( const char * ) & peer - > mac , context - > port , packet , sizeof ( packet ) , 0 , ADHOC_F_NONBLOCK ) ;
context - > socketlock - > unlock ( ) ;
}
}
}
}
/**
* Tell Established Peers that we ' re shutting the Networking Layer down
* @ param context Matching Context Pointer
*/
void sendByePacket ( SceNetAdhocMatchingContext * context )
{
// Iterate Peers
SceNetAdhocMatchingMemberInternal * peer = context - > peerlist ; for ( ; peer ! = NULL ; peer = peer - > next )
{
// Peer of Interest
if ( peer - > state = = PSP_ADHOC_MATCHING_PEER_PARENT | | peer - > state = = PSP_ADHOC_MATCHING_PEER_CHILD | | peer - > state = = PSP_ADHOC_MATCHING_PEER_P2P )
{
// Bye Opcode
uint8_t opcode = PSP_ADHOC_MATCHING_PACKET_BYE ;
// Send Bye Packet
context - > socketlock - > lock ( ) ;
sceNetAdhocPdpSend ( context - > socket , ( const char * ) & peer - > mac , context - > port , & opcode , sizeof ( opcode ) , 0 , ADHOC_F_NONBLOCK ) ;
context - > socketlock - > unlock ( ) ;
}
}
}
/**
* Handle Ping Packet
* @ param context Matching Context Pointer
* @ param sendermac Packet Sender MAC
*/
void actOnPingPacket ( SceNetAdhocMatchingContext * context , SceNetEtherAddr * sendermac )
{
// Find Peer
SceNetAdhocMatchingMemberInternal * peer = findPeer ( context , sendermac ) ;
// Found Peer
if ( peer ! = NULL )
{
// Update Receive Timer
peer - > lastping = CoreTiming : : GetGlobalTimeUsScaled ( ) ; //real_time_now()*1000000.0;
}
}
/**
* Handle Hello Packet
* @ param context Matching Context Pointer
* @ param sendermac Packet Sender MAC
* @ param length Packet Length
*/
void actOnHelloPacket ( SceNetAdhocMatchingContext * context , SceNetEtherAddr * sendermac , int32_t length )
{
// Interested in Hello Data
if ( ( context - > mode = = PSP_ADHOC_MATCHING_MODE_CHILD & & findParent ( context ) = = NULL ) | | ( context - > mode = = PSP_ADHOC_MATCHING_MODE_P2P & & findP2P ( context ) = = NULL ) )
{
// Complete Packet Header available
if ( length > = 5 )
{
// Extract Optional Data Length
int optlen = 0 ; memcpy ( & optlen , context - > rxbuf + 1 , sizeof ( optlen ) ) ;
// Complete Valid Packet available
if ( optlen > = 0 & & length > = ( 5 + optlen ) )
{
// Set Default Null Data
void * opt = NULL ;
// Extract Optional Data Pointer
if ( optlen > 0 ) opt = context - > rxbuf + 5 ;
// Find Peer
SceNetAdhocMatchingMemberInternal * peer = findPeer ( context , sendermac ) ;
// Peer not found
if ( peer = = NULL )
{
// Allocate Memory
peer = ( SceNetAdhocMatchingMemberInternal * ) malloc ( sizeof ( SceNetAdhocMatchingMemberInternal ) ) ;
// Allocated Memory
if ( peer ! = NULL )
{
// Clear Memory
memset ( peer , 0 , sizeof ( SceNetAdhocMatchingMemberInternal ) ) ;
// Copy Sender MAC
peer - > mac = * sendermac ;
// Set Peer State
peer - > state = PSP_ADHOC_MATCHING_PEER_OFFER ;
// Initialize Ping Timer
peer - > lastping = CoreTiming : : GetGlobalTimeUsScaled ( ) ; //real_time_now()*1000000.0;
// Link Peer into List
peer - > next = context - > peerlist ;
context - > peerlist = peer ;
}
}
// Peer available now
if ( peer ! = NULL )
{
// Spawn Hello Event
spawnLocalEvent ( context , PSP_ADHOC_MATCHING_EVENT_HELLO , sendermac , optlen , opt ) ;
}
}
}
}
}
/**
* Handle Join Packet
* @ param context Matching Context Pointer
* @ param sendermac Packet Sender MAC
* @ param length Packet Length
*/
void actOnJoinPacket ( SceNetAdhocMatchingContext * context , SceNetEtherAddr * sendermac , int32_t length )
{
// Not a child mode context
if ( context - > mode ! = PSP_ADHOC_MATCHING_MODE_CHILD )
{
// We still got a unoccupied slot in our room (Parent / P2P)
if ( ( context - > mode = = PSP_ADHOC_MATCHING_MODE_PARENT & & countChildren ( context ) < ( context - > maxpeers - 1 ) ) | | ( context - > mode = = PSP_ADHOC_MATCHING_MODE_P2P & & findP2P ( context ) = = NULL ) )
{
// Complete Packet Header available
if ( length > = 5 )
{
// Extract Optional Data Length
int optlen = 0 ; memcpy ( & optlen , context - > rxbuf + 1 , sizeof ( optlen ) ) ;
// Complete Valid Packet available
if ( optlen > = 0 & & length > = ( 5 + optlen ) )
{
// Set Default Null Data
void * opt = NULL ;
// Extract Optional Data Pointer
if ( optlen > 0 ) opt = context - > rxbuf + 5 ;
// Find Peer
SceNetAdhocMatchingMemberInternal * peer = findPeer ( context , sendermac ) ;
// If we got the peer in the table already and are a parent, there is nothing left to be done.
// This is because the only way a parent can know of a child is via a join request...
// If we thus know of a possible child, then we already had a previous join request thus no need for double tapping.
if ( peer ! = NULL & & context - > mode = = PSP_ADHOC_MATCHING_MODE_PARENT ) return ;
// New Peer
if ( peer = = NULL )
{
// Allocate Memory
peer = ( SceNetAdhocMatchingMemberInternal * ) malloc ( sizeof ( SceNetAdhocMatchingMemberInternal ) ) ;
// Allocated Memory
if ( peer ! = NULL )
{
// Clear Memory
memset ( peer , 0 , sizeof ( SceNetAdhocMatchingMemberInternal ) ) ;
// Copy Sender MAC
peer - > mac = * sendermac ;
// Set Peer State
peer - > state = PSP_ADHOC_MATCHING_PEER_INCOMING_REQUEST ;
// Initialize Ping Timer
peer - > lastping = CoreTiming : : GetGlobalTimeUsScaled ( ) ; //real_time_now()*1000000.0;
// Link Peer into List
peer - > next = context - > peerlist ;
context - > peerlist = peer ;
// Spawn Request Event
spawnLocalEvent ( context , PSP_ADHOC_MATCHING_EVENT_REQUEST , sendermac , optlen , opt ) ;
// Return Success
return ;
}
}
// Existing Peer (this case is only reachable for P2P mode)
else
{
// Set Peer State
peer - > state = PSP_ADHOC_MATCHING_PEER_INCOMING_REQUEST ;
// Spawn Request Event
spawnLocalEvent ( context , PSP_ADHOC_MATCHING_EVENT_REQUEST , sendermac , optlen , opt ) ;
// Return Success
return ;
}
}
}
}
INFO_LOG ( SCENET , " Join Event(2) Rejected " ) ;
// Auto-Reject Player
sendCancelPacket ( context , sendermac , 0 , NULL ) ;
}
}
/**
* Handle Accept Packet
* @ param context Matching Context Pointer
* @ param sendermac Packet Sender MAC
* @ param length Packet Length
*/
void actOnAcceptPacket ( SceNetAdhocMatchingContext * context , SceNetEtherAddr * sendermac , uint32_t length )
{
// Not a parent context
if ( context - > mode ! = PSP_ADHOC_MATCHING_MODE_PARENT )
{
// Don't have a master yet
if ( ( context - > mode = = PSP_ADHOC_MATCHING_MODE_CHILD & & findParent ( context ) = = NULL ) | | ( context - > mode = = PSP_ADHOC_MATCHING_MODE_P2P & & findP2P ( context ) = = NULL ) )
{
// Complete Packet Header available
if ( length > = 9 )
{
// Extract Optional Data Length
int optlen = 0 ; memcpy ( & optlen , context - > rxbuf + 1 , sizeof ( optlen ) ) ;
// Extract Sibling Count
int siblingcount = 0 ; memcpy ( & siblingcount , context - > rxbuf + 5 , sizeof ( siblingcount ) ) ;
// Complete Valid Packet available
if ( optlen > = 0 & & length > = ( 9 + optlen + sizeof ( SceNetEtherAddr ) * siblingcount ) )
{
// Set Default Null Data
void * opt = NULL ;
// Extract Optional Data Pointer
if ( optlen > 0 ) opt = context - > rxbuf + 9 ;
// Sibling MAC Array Null Data
SceNetEtherAddr * siblings = NULL ;
// Extract Optional Sibling MAC Array
if ( siblingcount > 0 ) siblings = ( SceNetEtherAddr * ) ( context - > rxbuf + 9 + optlen ) ;
// Find Outgoing Request
SceNetAdhocMatchingMemberInternal * request = findOutgoingRequest ( context ) ;
// We are waiting for a answer to our request...
if ( request ! = NULL )
{
// Find Peer
SceNetAdhocMatchingMemberInternal * peer = findPeer ( context , sendermac ) ;
// It's the answer we wanted!
if ( request = = peer )
{
// Change Peer State
peer - > state = ( context - > mode = = PSP_ADHOC_MATCHING_MODE_CHILD ) ? ( PSP_ADHOC_MATCHING_PEER_PARENT ) : ( PSP_ADHOC_MATCHING_PEER_P2P ) ;
// Remove Unneeded Peer Information
postAcceptCleanPeerList ( context ) ;
// Add Sibling Peers
if ( context - > mode = = PSP_ADHOC_MATCHING_MODE_CHILD ) postAcceptAddSiblings ( context , siblingcount , siblings ) ;
// IMPORTANT! The Event Order here is ok!
// Internally the Event Stack appends to the front, so the order will be switched around.
// Spawn Established Event
spawnLocalEvent ( context , PSP_ADHOC_MATCHING_EVENT_ESTABLISHED , sendermac , 0 , NULL ) ;
// Spawn Accept Event
spawnLocalEvent ( context , PSP_ADHOC_MATCHING_EVENT_ACCEPT , sendermac , optlen , opt ) ;
}
}
}
}
}
}
}
/**
* Handle Cancel Packet
* @ param context Matching Context Pointer
* @ param sendermac Packet Sender MAC
* @ param length Packet Length
*/
void actOnCancelPacket ( SceNetAdhocMatchingContext * context , SceNetEtherAddr * sendermac , int32_t length )
{
// Find Peer
SceNetAdhocMatchingMemberInternal * peer = findPeer ( context , sendermac ) ;
// Get Parent
SceNetAdhocMatchingMemberInternal * parent = findParent ( context ) ;
// Get Outgoing Join Request
SceNetAdhocMatchingMemberInternal * request = findOutgoingRequest ( context ) ;
// Get P2P Partner
SceNetAdhocMatchingMemberInternal * p2p = findP2P ( context ) ;
// Interest Condition fulfilled
if ( peer ! = NULL )
{
// Complete Packet Header available
if ( length > = 5 )
{
// Extract Optional Data Length
int optlen = 0 ; memcpy ( & optlen , context - > rxbuf + 1 , sizeof ( optlen ) ) ;
// Complete Valid Packet available
if ( optlen > = 0 & & length > = ( 5 + optlen ) )
{
// Set Default Null Data
void * opt = NULL ;
// Extract Optional Data Pointer
if ( optlen > 0 ) opt = context - > rxbuf + 5 ;
// Child Mode
if ( context - > mode = = PSP_ADHOC_MATCHING_MODE_CHILD )
{
// Join Request denied
if ( request = = peer )
{
// Spawn Deny Event
spawnLocalEvent ( context , PSP_ADHOC_MATCHING_EVENT_DENY , sendermac , optlen , opt ) ;
// Delete Peer from List
deletePeer ( context , peer ) ;
}
// Kicked from Room
else if ( parent = = peer )
{
// Iterate Peers
SceNetAdhocMatchingMemberInternal * item = context - > peerlist ; for ( ; item ! = NULL ; item = item - > next )
{
// Established Peer
if ( item - > state = = PSP_ADHOC_MATCHING_PEER_CHILD | | item - > state = = PSP_ADHOC_MATCHING_PEER_PARENT )
{
// Spawn Leave / Kick Event
spawnLocalEvent ( context , PSP_ADHOC_MATCHING_EVENT_LEAVE , & item - > mac , optlen , opt ) ;
}
}
// Delete Peer from List
clearPeerList ( context ) ;
}
}
// Parent Mode
else if ( context - > mode = = PSP_ADHOC_MATCHING_MODE_PARENT )
{
// Cancel Join Request
if ( peer - > state = = PSP_ADHOC_MATCHING_PEER_INCOMING_REQUEST )
{
// Spawn Request Cancel Event
spawnLocalEvent ( context , PSP_ADHOC_MATCHING_EVENT_CANCEL , sendermac , optlen , opt ) ;
// Delete Peer from List
deletePeer ( context , peer ) ;
}
// Leave Room
else if ( peer - > state = = PSP_ADHOC_MATCHING_PEER_CHILD )
{
// Spawn Leave / Kick Event
spawnLocalEvent ( context , PSP_ADHOC_MATCHING_EVENT_LEAVE , sendermac , optlen , opt ) ;
// Delete Peer from List
deletePeer ( context , peer ) ;
}
}
// P2P Mode
else
{
// Join Request denied
if ( request = = peer )
{
// Spawn Deny Event
spawnLocalEvent ( context , PSP_ADHOC_MATCHING_EVENT_DENY , sendermac , optlen , opt ) ;
// Delete Peer from List
deletePeer ( context , peer ) ;
}
// Kicked from Room
else if ( p2p = = peer )
{
// Spawn Leave / Kick Event
spawnLocalEvent ( context , PSP_ADHOC_MATCHING_EVENT_LEAVE , sendermac , optlen , opt ) ;
// Delete Peer from List
deletePeer ( context , peer ) ;
}
// Cancel Join Request
else if ( peer - > state = = PSP_ADHOC_MATCHING_PEER_INCOMING_REQUEST )
{
// Spawn Request Cancel Event
spawnLocalEvent ( context , PSP_ADHOC_MATCHING_EVENT_CANCEL , sendermac , optlen , opt ) ;
// Delete Peer from List
deletePeer ( context , peer ) ;
}
}
}
}
}
}
/**
* Handle Bulk Data Packet
* @ param context Matching Context Pointer
* @ param sendermac Packet Sender MAC
* @ param length Packet Length
*/
void actOnBulkDataPacket ( SceNetAdhocMatchingContext * context , SceNetEtherAddr * sendermac , int32_t length )
{
// Find Peer
SceNetAdhocMatchingMemberInternal * peer = findPeer ( context , sendermac ) ;
// Established Peer
if ( peer ! = NULL & & (
( context - > mode = = PSP_ADHOC_MATCHING_MODE_PARENT & & peer - > state = = PSP_ADHOC_MATCHING_PEER_CHILD ) | |
( context - > mode = = PSP_ADHOC_MATCHING_MODE_CHILD & & ( peer - > state = = PSP_ADHOC_MATCHING_PEER_CHILD | | peer - > state = = PSP_ADHOC_MATCHING_PEER_PARENT ) ) | |
( context - > mode = = PSP_ADHOC_MATCHING_MODE_P2P & & peer - > state = = PSP_ADHOC_MATCHING_PEER_P2P ) ) )
{
// Complete Packet Header available
if ( length > 5 )
{
// Extract Data Length
int datalen = 0 ; memcpy ( & datalen , context - > rxbuf + 1 , sizeof ( datalen ) ) ;
// Complete Valid Packet available
if ( datalen > 0 & & length > = ( 5 + datalen ) )
{
// Extract Data
void * data = context - > rxbuf + 5 ;
// Spawn Data Event
spawnLocalEvent ( context , PSP_ADHOC_MATCHING_EVENT_DATA , sendermac , datalen , data ) ;
}
}
}
}
/**
* Handle Birth Packet
* @ param context Matching Context Pointer
* @ param sendermac Packet Sender MAC
* @ param length Packet Length
*/
void actOnBirthPacket ( SceNetAdhocMatchingContext * context , SceNetEtherAddr * sendermac , uint32_t length )
{
// Find Peer
SceNetAdhocMatchingMemberInternal * peer = findPeer ( context , sendermac ) ;
// Valid Circumstances
if ( peer ! = NULL & & context - > mode = = PSP_ADHOC_MATCHING_MODE_CHILD & & peer = = findParent ( context ) )
{
// Complete Packet available
if ( length > = ( 1 + sizeof ( SceNetEtherAddr ) ) )
{
// Extract Child MAC
SceNetEtherAddr mac ;
memcpy ( & mac , context - > rxbuf + 1 , sizeof ( SceNetEtherAddr ) ) ;
// Allocate Memory (If this fails... we are fucked.)
SceNetAdhocMatchingMemberInternal * sibling = ( SceNetAdhocMatchingMemberInternal * ) malloc ( sizeof ( SceNetAdhocMatchingMemberInternal ) ) ;
// Allocated Memory
if ( sibling ! = NULL )
{
// Clear Memory
memset ( sibling , 0 , sizeof ( SceNetAdhocMatchingMemberInternal ) ) ;
// Save MAC Address
sibling - > mac = mac ;
// Set Peer State
sibling - > state = PSP_ADHOC_MATCHING_PEER_CHILD ;
// Initialize Ping Timer
peer - > lastping = CoreTiming : : GetGlobalTimeUsScaled ( ) ; //real_time_now()*1000000.0;
peerlock . lock ( ) ;
// Link Peer
sibling - > next = context - > peerlist ;
context - > peerlist = sibling ;
peerlock . unlock ( ) ;
// Spawn Established Event
spawnLocalEvent ( context , PSP_ADHOC_MATCHING_EVENT_ESTABLISHED , & sibling - > mac , 0 , NULL ) ;
}
}
}
}
/**
* Handle Death Packet
* @ param context Matching Context Pointer
* @ param sendermac Packet Sender MAC
* @ param length Packet Length
*/
void actOnDeathPacket ( SceNetAdhocMatchingContext * context , SceNetEtherAddr * sendermac , uint32_t length )
{
// Find Peer
SceNetAdhocMatchingMemberInternal * peer = findPeer ( context , sendermac ) ;
// Valid Circumstances
if ( peer ! = NULL & & context - > mode = = PSP_ADHOC_MATCHING_MODE_CHILD & & peer = = findParent ( context ) )
{
// Complete Packet available
if ( length > = ( 1 + sizeof ( SceNetEtherAddr ) ) )
{
// Extract Child MAC
SceNetEtherAddr mac ;
memcpy ( & mac , context - > rxbuf + 1 , sizeof ( SceNetEtherAddr ) ) ;
// Find Peer
SceNetAdhocMatchingMemberInternal * deadkid = findPeer ( context , & mac ) ;
// Valid Sibling
if ( deadkid - > state = = PSP_ADHOC_MATCHING_PEER_CHILD )
{
// Spawn Leave Event
spawnLocalEvent ( context , PSP_ADHOC_MATCHING_EVENT_LEAVE , & mac , 0 , NULL ) ;
// Delete Peer
deletePeer ( context , deadkid ) ;
}
}
}
}
/**
* Handle Bye Packet
* @ param context Matching Context Pointer
* @ param sendermac Packet Sender MAC
*/
void actOnByePacket ( SceNetAdhocMatchingContext * context , SceNetEtherAddr * sendermac )
{
// Find Peer
SceNetAdhocMatchingMemberInternal * peer = findPeer ( context , sendermac ) ;
// We know this guy
if ( peer ! = NULL )
{
// P2P or Child Bye
if ( ( context - > mode = = PSP_ADHOC_MATCHING_MODE_PARENT & & peer - > state = = PSP_ADHOC_MATCHING_PEER_CHILD ) | |
( context - > mode = = PSP_ADHOC_MATCHING_MODE_CHILD & & peer - > state = = PSP_ADHOC_MATCHING_PEER_CHILD ) | |
( context - > mode = = PSP_ADHOC_MATCHING_MODE_P2P & & peer - > state = = PSP_ADHOC_MATCHING_PEER_P2P ) )
{
// Spawn Leave / Kick Event
spawnLocalEvent ( context , PSP_ADHOC_MATCHING_EVENT_BYE , sendermac , 0 , NULL ) ;
// Delete Peer
deletePeer ( context , peer ) ;
}
// Parent Bye
else if ( context - > mode = = PSP_ADHOC_MATCHING_MODE_CHILD & & peer - > state = = PSP_ADHOC_MATCHING_PEER_PARENT )
{
// Iterate Peers
SceNetAdhocMatchingMemberInternal * item = context - > peerlist ; for ( ; item ! = NULL ; item = item - > next )
{
// Established Peer
if ( item - > state = = PSP_ADHOC_MATCHING_PEER_CHILD | | item - > state = = PSP_ADHOC_MATCHING_PEER_PARENT )
{
// Spawn Leave / Kick Event
spawnLocalEvent ( context , PSP_ADHOC_MATCHING_EVENT_BYE , & item - > mac , 0 , NULL ) ;
}
}
// Delete Peer from List
clearPeerList ( context ) ;
}
}
}
/**
* Matching Event Dispatcher Thread
* @ param args sizeof ( SceNetAdhocMatchingContext * )
* @ param argp SceNetAdhocMatchingContext *
* @ return Exit Point is never reached . . .
*/
int matchingEventThread ( int matchingId )
{
u32 bufLen = 0 ;
u32 bufAddr = 0 ;
// Multithreading Lock
peerlock . lock ( ) ;
// Cast Context
SceNetAdhocMatchingContext * context = findMatchingContext ( matchingId ) ;
// Multithreading Unlock
peerlock . unlock ( ) ;
// Log Startup
INFO_LOG ( SCENET , " EventLoop: Begin of EventLoop[%i] Thread " , matchingId ) ;
// Run while needed...
if ( context ! = NULL ) {
//static u32_le args[5] = { 0, 0, 0, 0, 0 }; // Need to be global/static so it can be accessed from a different thread
u32_le * args = context - > handlerArgs ;
while ( context - > eventRunning ) // (context->eventThread.get_id() != NULL)
{
// Messages on Stack ready for processing
if ( context - > event_stack ! = NULL )
{
// Claim Stack
context - > eventlock - > lock ( ) ;
// Iterate Message List
ThreadMessage * msg = context - > event_stack ; for ( ; msg ! = NULL ; msg = msg - > next )
{
// Default Optional Data
void * opt = NULL ;
// Grab Optional Data
if ( msg - > optlen > 0 ) opt = ( ( u8 * ) msg ) + sizeof ( ThreadMessage ) ; //&msg[1]
// Log Matching Events
2015-04-08 19:15:41 +00:00
INFO_LOG ( SCENET , " EventLoop[%d]: Matching Event [%d=%s] OptSize=%d " , matchingId , msg - > opcode , getMatchingEventStr ( msg - > opcode ) , msg - > optlen ) ;
2014-07-31 18:55:42 +00:00
context - > eventlock - > unlock ( ) ; // Unlock to prevent race-condition with other threads due to recursive lock
// Call Event Handler
//context->handler(context->id, msg->opcode, &msg->mac, msg->optlen, opt);
// Notify Event Handlers
notifyMatchingHandler ( context , msg , opt , bufAddr , bufLen , args ) ;
context - > eventlock - > lock ( ) ; // Lock again
}
// Clear Event Message Stack
clearStack ( context , PSP_ADHOC_MATCHING_EVENT_STACK ) ;
// Free Stack
context - > eventlock - > unlock ( ) ;
}
// Share CPU Time
sleep_ms ( 1 ) ; //10 //sceKernelDelayThread(10000);
// Don't do anything if it's paused, otherwise the log will be flooded
while ( Core_IsStepping ( ) & & context - > eventRunning ) sleep_ms ( 1 ) ;
}
// Process Last Messages
if ( context - > event_stack ! = NULL )
{
// Claim Stack
context - > eventlock - > lock ( ) ;
// Iterate Message List
ThreadMessage * msg = context - > event_stack ; for ( ; msg ! = NULL ; msg = msg - > next )
{
// Default Optional Data
void * opt = NULL ;
// Grab Optional Data
if ( msg - > optlen > 0 ) opt = ( ( u8 * ) msg ) + sizeof ( ThreadMessage ) ; //&msg[1]
INFO_LOG ( SCENET , " EventLoop[%d]: Matching Event [EVENT=%d] \n " , matchingId , msg - > opcode ) ;
context - > eventlock - > unlock ( ) ;
// Original Call Event Handler
//context->handler(context->id, msg->opcode, &msg->mac, msg->optlen, opt);
// Notify Event Handlers
notifyMatchingHandler ( context , msg , opt , bufAddr , bufLen , args ) ;
context - > eventlock - > lock ( ) ;
}
// Clear Event Message Stack
clearStack ( context , PSP_ADHOC_MATCHING_EVENT_STACK ) ;
// Free Stack
context - > eventlock - > unlock ( ) ;
}
// Delete Pointer Reference (and notify caller about finished cleanup)
//context->eventThread = NULL;
}
// Log Shutdown
INFO_LOG ( SCENET , " EventLoop: End of EventLoop[%i] Thread " , matchingId ) ;
// Free memory
if ( Memory : : IsValidAddress ( bufAddr ) ) userMemory . Free ( bufAddr ) ;
// Return Zero to shut up Compiler (never reached anyway)
return 0 ;
}
/**
* Matching IO Handler Thread
* @ param args sizeof ( SceNetAdhocMatchingContext * )
* @ param argp SceNetAdhocMatchingContext *
* @ return Exit Point is never reached . . .
*/
int matchingInputThread ( int matchingId )
{
// Multithreading Lock
peerlock . lock ( ) ;
// Cast Context
SceNetAdhocMatchingContext * context = findMatchingContext ( matchingId ) ;
// Multithreading Unlock
peerlock . unlock ( ) ;
// Last Ping
u64_le lastping = 0 ;
// Last Hello
u64_le lasthello = 0 ;
u64_le now ;
// Log Startup
INFO_LOG ( SCENET , " InputLoop: Begin of InputLoop[%i] Thread " , matchingId ) ;
// Run while needed...
if ( context ! = NULL ) {
while ( context - > inputRunning )
{
now = CoreTiming : : GetGlobalTimeUsScaled ( ) ; //real_time_now()*1000000.0;
// Hello Message Sending Context with unoccupied Slots
if ( ( context - > mode = = PSP_ADHOC_MATCHING_MODE_PARENT & & ( countChildren ( context ) < ( context - > maxpeers - 1 ) ) ) | | ( context - > mode = = PSP_ADHOC_MATCHING_MODE_P2P & & findP2P ( context ) = = NULL ) )
{
// Hello Message Broadcast necessary because of Hello Interval
if ( context - > hello_int > 0 )
if ( ( now - lasthello ) > = context - > hello_int )
{
// Broadcast Hello Message
broadcastHelloMessage ( context ) ;
// Update Hello Timer
lasthello = now ;
}
}
// Ping Required
if ( context - > keepalive_int > 0 )
if ( ( now - lastping ) > = context - > keepalive_int )
{
// Broadcast Ping Message
broadcastPingMessage ( context ) ;
// Update Ping Timer
lastping = now ;
}
// Messages on Stack ready for processing
if ( context - > input_stack ! = NULL )
{
// Claim Stack
context - > inputlock - > lock ( ) ;
// Iterate Message List
ThreadMessage * msg = context - > input_stack ;
for ( ; msg ! = NULL ; msg = msg - > next )
{
// Default Optional Data
void * opt = NULL ;
// Grab Optional Data
if ( msg - > optlen > 0 ) opt = ( ( u8 * ) msg ) + sizeof ( ThreadMessage ) ;
context - > inputlock - > unlock ( ) ; // Unlock to prevent race condition when locking peerlock
// Send Accept Packet
if ( msg - > opcode = = PSP_ADHOC_MATCHING_PACKET_ACCEPT ) sendAcceptPacket ( context , & msg - > mac , msg - > optlen , opt ) ;
// Send Join Packet
else if ( msg - > opcode = = PSP_ADHOC_MATCHING_PACKET_JOIN ) sendJoinPacket ( context , & msg - > mac , msg - > optlen , opt ) ;
// Send Cancel Packet
else if ( msg - > opcode = = PSP_ADHOC_MATCHING_PACKET_CANCEL ) sendCancelPacket ( context , & msg - > mac , msg - > optlen , opt ) ;
// Send Bulk Data Packet
else if ( msg - > opcode = = PSP_ADHOC_MATCHING_PACKET_BULK ) sendBulkDataPacket ( context , & msg - > mac , msg - > optlen , opt ) ;
// Send Birth Packet
else if ( msg - > opcode = = PSP_ADHOC_MATCHING_PACKET_BIRTH ) sendBirthPacket ( context , & msg - > mac ) ;
// Cancel Bulk Data Transfer (does nothing as of now as we fire and forget anyway) // Do we need to check DeathPacket and BytePacket here?
// else if(msg->opcode == PSP_ADHOC_MATCHING_PACKET_BULK_ABORT) blabla;
context - > inputlock - > lock ( ) ; // Lock again
}
// Clear IO Message Stack
clearStack ( context , PSP_ADHOC_MATCHING_INPUT_STACK ) ;
// Free Stack
context - > inputlock - > unlock ( ) ;
}
// Receive PDP Datagram
SceNetEtherAddr sendermac ;
uint16_t senderport ;
int rxbuflen = context - > rxbuflen ;
context - > socketlock - > lock ( ) ;
int recvresult = sceNetAdhocPdpRecv ( context - > socket , & sendermac , & senderport , context - > rxbuf , & rxbuflen , 0 , ADHOC_F_NONBLOCK ) ;
context - > socketlock - > unlock ( ) ;
// Received Data from a Sender that interests us
if ( recvresult = = 0 & & rxbuflen > 0 & & context - > port = = senderport )
{
// Log Receive Success
if ( context - > rxbuf [ 0 ] > 1 ) {
2015-01-04 13:09:41 +00:00
INFO_LOG ( SCENET , " InputLoop[%d]: Received %d Bytes (Opcode[%d]=%s) " , matchingId , rxbuflen , context - > rxbuf [ 0 ] , getMatchingOpcodeStr ( context - > rxbuf [ 0 ] ) ) ;
2014-07-31 18:55:42 +00:00
}
// Update Peer Timestamp
peerlock . lock ( ) ;
SceNetAdhocctlPeerInfo * peer = findFriend ( & sendermac ) ;
if ( peer ! = NULL ) {
now = CoreTiming : : GetGlobalTimeUsScaled ( ) ;
u64_le delta = now - peer - > last_recv ;
DEBUG_LOG ( SCENET , " Timestamp Delta: %llu (%llu - %llu) " , delta , now , peer - > last_recv ) ;
if ( /*context->rxbuf[0] > 0 &&*/ peer - > last_recv ! = 0 ) peer - > last_recv = now ; // - context->keepalive_int; // May need to deduce by ping interval to prevent Dissidia 012 unable to see other players (ie. disappearing issue)
}
peerlock . unlock ( ) ;
// Ping Packet
if ( context - > rxbuf [ 0 ] = = PSP_ADHOC_MATCHING_PACKET_PING ) actOnPingPacket ( context , & sendermac ) ;
// Hello Packet
else if ( context - > rxbuf [ 0 ] = = PSP_ADHOC_MATCHING_PACKET_HELLO ) actOnHelloPacket ( context , & sendermac , rxbuflen ) ;
// Join Packet
else if ( context - > rxbuf [ 0 ] = = PSP_ADHOC_MATCHING_PACKET_JOIN ) actOnJoinPacket ( context , & sendermac , rxbuflen ) ;
// Accept Packet
else if ( context - > rxbuf [ 0 ] = = PSP_ADHOC_MATCHING_PACKET_ACCEPT ) actOnAcceptPacket ( context , & sendermac , rxbuflen ) ;
// Cancel Packet
else if ( context - > rxbuf [ 0 ] = = PSP_ADHOC_MATCHING_PACKET_CANCEL ) actOnCancelPacket ( context , & sendermac , rxbuflen ) ;
// Bulk Data Packet
else if ( context - > rxbuf [ 0 ] = = PSP_ADHOC_MATCHING_PACKET_BULK ) actOnBulkDataPacket ( context , & sendermac , rxbuflen ) ;
// Birth Packet
else if ( context - > rxbuf [ 0 ] = = PSP_ADHOC_MATCHING_PACKET_BIRTH ) actOnBirthPacket ( context , & sendermac , rxbuflen ) ;
// Death Packet
else if ( context - > rxbuf [ 0 ] = = PSP_ADHOC_MATCHING_PACKET_DEATH ) actOnDeathPacket ( context , & sendermac , rxbuflen ) ;
// Bye Packet
else if ( context - > rxbuf [ 0 ] = = PSP_ADHOC_MATCHING_PACKET_BYE ) actOnByePacket ( context , & sendermac ) ;
// Ignore Incoming Trash Data
}
// Handle Peer Timeouts
handleTimeout ( context ) ;
// Share CPU Time
sleep_ms ( 1 ) ; //10 //sceKernelDelayThread(10000);
// Don't do anything if it's paused, otherwise the log will be flooded
while ( Core_IsStepping ( ) & & context - > inputRunning ) sleep_ms ( 1 ) ;
}
// Send Bye Messages
sendByePacket ( context ) ;
// Free Peer List Buffer
clearPeerList ( context ) ; //deleteAllMembers(context);
// Delete Pointer Reference (and notify caller about finished cleanup)
//context->inputThread = NULL;
}
// Log Shutdown
INFO_LOG ( SCENET , " InputLoop: End of InputLoop[%i] Thread " , matchingId ) ;
// Terminate Thread
//sceKernelExitDeleteThread(0);
// Return Zero to shut up Compiler (never reached anyway)
return 0 ;
}