2020-12-05 13:08:24 +01:00
# include "stdafx.h"
2020-03-04 14:55:35 +01:00
# include <thread>
# include "Emu/system_config.h"
# include "np_handler.h"
# include "Emu/Cell/PPUModule.h"
# include "Emu/Cell/Modules/sceNp.h"
# include "Emu/Cell/Modules/sceNp2.h"
# include "Emu/Cell/Modules/cellNetCtl.h"
# include "Utilities/StrUtil.h"
# include "Emu/Cell/Modules/cellSysutil.h"
# include "Emu/IdManager.h"
2020-08-27 21:47:04 +02:00
# include "np_structs_extra.h"
# include "Emu/System.h"
# include "Emu/NP/rpcn_config.h"
2020-11-10 09:55:49 +01:00
# include "Emu/NP/np_contexts.h"
2020-03-04 14:55:35 +01:00
# ifdef _WIN32
# include <winsock2.h>
# include <WS2tcpip.h>
2020-10-11 05:02:33 +02:00
# include <iphlpapi.h>
2020-03-04 14:55:35 +01:00
# else
# include <sys/socket.h>
# include <netinet/in.h>
2020-12-09 16:04:52 +01:00
# include <net/if.h>
2020-03-04 14:55:35 +01:00
# include <arpa/inet.h>
2020-08-27 21:47:04 +02:00
# include <netdb.h>
2020-03-04 14:55:35 +01:00
# include <unistd.h>
# endif
2020-10-11 05:02:33 +02:00
# ifdef __FreeBSD__
# include <ifaddrs.h>
# include <net/if_dl.h>
# endif
2020-12-18 15:43:34 +01:00
# include "util/asm.hpp"
2020-03-04 15:08:40 +01:00
LOG_CHANNEL ( sys_net ) ;
LOG_CHANNEL ( sceNp2 ) ;
LOG_CHANNEL ( sceNp ) ;
2020-03-04 14:55:35 +01:00
2020-08-27 21:47:04 +02:00
LOG_CHANNEL ( rpcn_log , " rpcn " ) ;
LOG_CHANNEL ( nph_log , " NPHandler " ) ;
2020-03-04 14:55:35 +01:00
np_handler : : np_handler ( )
{
2020-08-27 21:47:04 +02:00
g_cfg_rpcn . load ( ) ;
2020-03-04 14:55:35 +01:00
is_connected = ( g_cfg . net . net_active = = np_internet_status : : enabled ) ;
is_psn_active = ( g_cfg . net . psn_status > = np_psn_status : : fake ) ;
if ( get_net_status ( ) = = CELL_NET_CTL_STATE_IPObtained )
{
2020-08-27 21:47:04 +02:00
if ( ! discover_ip_address ( ) )
2020-03-04 14:55:35 +01:00
{
2020-08-27 21:47:04 +02:00
nph_log . error ( " Failed to discover local IP! " ) ;
2020-03-04 14:55:35 +01:00
is_connected = false ;
2020-08-27 21:47:04 +02:00
is_psn_active = false ;
2020-03-04 14:55:35 +01:00
}
2020-10-11 05:02:33 +02:00
if ( ! discover_ether_address ( ) )
{
nph_log . error ( " Failed to discover ethernet address! " ) ;
is_connected = false ;
is_psn_active = false ;
}
2020-03-04 14:55:35 +01:00
// Convert dns address
2020-08-27 21:47:04 +02:00
// TODO: recover actual user dns through OS specific API
in_addr conv { } ;
if ( ! inet_pton ( AF_INET , g_cfg . net . dns . to_string ( ) . c_str ( ) , & conv ) )
2020-03-04 14:55:35 +01:00
{
2020-08-27 21:47:04 +02:00
// Do not set to disconnected on invalid IP just error and continue using default(google's 8.8.8.8)
nph_log . error ( " Provided IP(%s) address for DNS is invalid! " , g_cfg . net . dns . to_string ( ) ) ;
}
else
{
dns_ip = conv . s_addr ;
2020-03-04 14:55:35 +01:00
}
// Init switch map for dns
2020-08-27 21:47:04 +02:00
auto swaps = fmt : : split ( g_cfg . net . swap_list . to_string ( ) , { " && " } ) ;
2020-12-18 08:39:54 +01:00
for ( usz i = 0 ; i < swaps . size ( ) ; i + + )
2020-03-04 14:55:35 +01:00
{
auto host_and_ip = fmt : : split ( swaps [ i ] , { " = " } ) ;
if ( host_and_ip . size ( ) ! = 2 )
2020-08-27 21:47:04 +02:00
{
nph_log . error ( " Pattern <%s> contains more than one '=' " , swaps [ i ] ) ;
2020-03-04 14:55:35 +01:00
continue ;
2020-08-27 21:47:04 +02:00
}
2020-03-04 14:55:35 +01:00
in_addr conv ;
if ( ! inet_pton ( AF_INET , host_and_ip [ 1 ] . c_str ( ) , & conv ) )
{
2020-08-27 21:47:04 +02:00
nph_log . error ( " IP(%s) provided for %s in the switch list is invalid! " , host_and_ip [ 1 ] , host_and_ip [ 0 ] ) ;
}
else
{
switch_map [ host_and_ip [ 0 ] ] = conv . s_addr ;
2020-03-04 14:55:35 +01:00
}
}
}
2020-08-27 21:47:04 +02:00
}
bool np_handler : : discover_ip_address ( )
{
2021-02-25 20:17:03 +01:00
hostname . clear ( ) ;
hostname . resize ( 1024 ) ;
2020-12-09 16:04:52 +01:00
2020-08-27 21:47:04 +02:00
if ( gethostname ( hostname . data ( ) , hostname . size ( ) ) = = - 1 )
{
nph_log . error ( " gethostname failed in IP discovery! " ) ;
return false ;
}
2020-12-09 16:04:52 +01:00
2021-02-25 20:17:03 +01:00
nph_log . notice ( " Hostname was determined to be %s " , hostname ) ;
2020-08-27 21:47:04 +02:00
hostent * host = gethostbyname ( hostname . data ( ) ) ;
if ( ! host )
2020-03-04 14:55:35 +01:00
{
2020-08-27 21:47:04 +02:00
nph_log . error ( " gethostbyname failed in IP discovery! " ) ;
return false ;
2020-03-04 14:55:35 +01:00
}
2020-08-27 21:47:04 +02:00
if ( host - > h_addrtype ! = AF_INET )
{
nph_log . error ( " Could only find IPv6 addresses for current host! " ) ;
return false ;
}
// First address is used for now, (TODO combobox with possible local addresses to use?)
local_ip_addr = * reinterpret_cast < u32 * > ( host - > h_addr_list [ 0 ] ) ;
// Set public address to local discovered address for now, may be updated later;
public_ip_addr = local_ip_addr ;
2020-10-11 05:02:33 +02:00
nph_log . notice ( " IP was determined to be %s " , ip_to_string ( local_ip_addr ) ) ;
2020-08-27 21:47:04 +02:00
return true ;
}
2020-10-11 05:02:33 +02:00
bool np_handler : : discover_ether_address ( )
{
# ifdef __FreeBSD__
ifaddrs * ifap ;
if ( getifaddrs ( & ifap ) = = 0 )
{
ifaddrs * p ;
for ( p = ifap ; p ; p = p - > ifa_next )
{
if ( p - > ifa_addr - > sa_family = = AF_LINK )
{
sockaddr_dl * sdp = reinterpret_cast < sockaddr_dl * > ( p - > ifa_addr ) ;
memcpy ( ether_address . data ( ) , sdp - > sdl_data + sdp - > sdl_nlen , 6 ) ;
freeifaddrs ( ifap ) ;
nph_log . notice ( " Determined Ethernet address to be %s " , ether_to_string ( ether_address ) ) ;
return true ;
}
}
freeifaddrs ( ifap ) ;
}
# elif defined(_WIN32)
std : : vector < u8 > adapter_infos ( sizeof ( IP_ADAPTER_INFO ) ) ;
ULONG size_infos = sizeof ( IP_ADAPTER_INFO ) ;
if ( GetAdaptersInfo ( reinterpret_cast < PIP_ADAPTER_INFO > ( adapter_infos . data ( ) ) , & size_infos ) = = ERROR_BUFFER_OVERFLOW )
adapter_infos . resize ( size_infos ) ;
if ( GetAdaptersInfo ( reinterpret_cast < PIP_ADAPTER_INFO > ( adapter_infos . data ( ) ) , & size_infos ) = = NO_ERROR & & size_infos )
{
PIP_ADAPTER_INFO info = reinterpret_cast < PIP_ADAPTER_INFO > ( adapter_infos . data ( ) ) ;
memcpy ( ether_address . data ( ) , info [ 0 ] . Address , 6 ) ;
nph_log . notice ( " Determined Ethernet address to be %s " , ether_to_string ( ether_address ) ) ;
return true ;
}
# else
ifreq ifr ;
ifconf ifc ;
char buf [ 1024 ] ;
int success = 0 ;
int sock = socket ( AF_INET , SOCK_DGRAM , IPPROTO_IP ) ;
if ( sock = = - 1 )
return false ;
ifc . ifc_len = sizeof ( buf ) ;
ifc . ifc_buf = buf ;
if ( ioctl ( sock , SIOCGIFCONF , & ifc ) = = - 1 )
return false ;
ifreq * it = ifc . ifc_req ;
const ifreq * const end = it + ( ifc . ifc_len / sizeof ( ifreq ) ) ;
for ( ; it ! = end ; + + it )
{
strcpy ( ifr . ifr_name , it - > ifr_name ) ;
if ( ioctl ( sock , SIOCGIFFLAGS , & ifr ) = = 0 )
{
if ( ! ( ifr . ifr_flags & IFF_LOOPBACK ) )
{
if ( ioctl ( sock , SIOCGIFHWADDR , & ifr ) = = 0 )
{
success = 1 ;
break ;
}
}
}
}
if ( success )
{
memcpy ( ether_address . data ( ) , ifr . ifr_hwaddr . sa_data , 6 ) ;
nph_log . notice ( " Determined Ethernet address to be %s " , ether_to_string ( ether_address ) ) ;
return true ;
}
# endif
return false ;
}
const std : : array < u8 , 6 > & np_handler : : get_ether_addr ( ) const
{
return ether_address ;
}
2021-02-25 20:17:03 +01:00
const std : : string & np_handler : : get_hostname ( ) const
{
return hostname ;
}
2020-08-27 21:47:04 +02:00
u32 np_handler : : get_local_ip_addr ( ) const
{
return local_ip_addr ;
}
u32 np_handler : : get_public_ip_addr ( ) const
{
return public_ip_addr ;
}
u32 np_handler : : get_dns_ip ( ) const
{
return dns_ip ;
}
s32 np_handler : : get_net_status ( ) const
{
return is_connected ? CELL_NET_CTL_STATE_IPObtained : CELL_NET_CTL_STATE_Disconnected ;
}
s32 np_handler : : get_psn_status ( ) const
{
return is_psn_active ? SCE_NP_MANAGER_STATUS_ONLINE : SCE_NP_MANAGER_STATUS_OFFLINE ;
}
const SceNpId & np_handler : : get_npid ( ) const
{
return npid ;
}
const SceNpOnlineId & np_handler : : get_online_id ( ) const
{
return npid . handle ;
}
const SceNpOnlineName & np_handler : : get_online_name ( ) const
{
return online_name ;
}
const SceNpAvatarUrl & np_handler : : get_avatar_url ( ) const
{
return avatar_url ;
}
std : : string np_handler : : ip_to_string ( u32 ip_addr )
{
std : : string result ;
in_addr addr ;
addr . s_addr = ip_addr ;
result = inet_ntoa ( addr ) ;
return result ;
}
2020-10-11 05:02:33 +02:00
std : : string np_handler : : ether_to_string ( std : : array < u8 , 6 > & ether )
{
return fmt : : format ( " %02X:%02X:%02X:%02X:%02X:%02X " , ether [ 0 ] , ether [ 1 ] , ether [ 2 ] , ether [ 3 ] , ether [ 4 ] , ether [ 5 ] ) ;
}
2021-01-20 07:59:41 +01:00
void np_handler : : string_to_npid ( const std : : string & str , SceNpId * npid )
2020-08-27 21:47:04 +02:00
{
2020-11-10 09:55:49 +01:00
memset ( npid , 0 , sizeof ( SceNpId ) ) ;
2021-01-20 07:59:41 +01:00
strcpy_trunc ( npid - > handle . data , str ) ;
2020-11-10 09:55:49 +01:00
// npid->reserved[0] = 1;
2020-08-27 21:47:04 +02:00
}
2021-01-20 07:59:41 +01:00
void np_handler : : string_to_online_name ( const std : : string & str , SceNpOnlineName * online_name )
2020-08-27 21:47:04 +02:00
{
2021-01-20 07:59:41 +01:00
strcpy_trunc ( online_name - > data , str ) ;
2020-08-27 21:47:04 +02:00
}
2021-01-20 07:59:41 +01:00
void np_handler : : string_to_avatar_url ( const std : : string & str , SceNpAvatarUrl * avatar_url )
2020-08-27 21:47:04 +02:00
{
2021-01-20 07:59:41 +01:00
strcpy_trunc ( avatar_url - > data , str ) ;
2020-03-04 14:55:35 +01:00
}
void np_handler : : init_NP ( u32 poolsize , vm : : ptr < void > poolptr )
{
// Init memory pool
mpool = poolptr ;
mpool_size = poolsize ;
mpool_avail = poolsize ;
mpool_allocs . clear ( ) ;
memset ( & npid , 0 , sizeof ( npid ) ) ;
memset ( & online_name , 0 , sizeof ( online_name ) ) ;
memset ( & avatar_url , 0 , sizeof ( avatar_url ) ) ;
if ( g_cfg . net . psn_status > = np_psn_status : : fake )
{
2020-08-27 21:47:04 +02:00
std : : string s_npid = g_cfg_rpcn . get_npid ( ) ;
2020-12-09 16:04:52 +01:00
ensure ( ! s_npid . empty ( ) ) ; // It should have been generated before this
2020-03-04 14:55:35 +01:00
2021-01-20 07:59:41 +01:00
np_handler : : string_to_npid ( s_npid , & npid ) ;
2021-03-02 12:59:19 +01:00
auto & sigh = g_fxo - > get < named_thread < signaling_handler > > ( ) ;
sigh . set_self_sig_info ( npid ) ;
2020-03-04 14:55:35 +01:00
}
switch ( g_cfg . net . psn_status )
{
case np_psn_status : : disabled :
break ;
case np_psn_status : : fake :
{
2020-08-27 21:47:04 +02:00
np_handler : : string_to_online_name ( " RPCS3's user " , & online_name ) ;
np_handler : : string_to_avatar_url ( " https://rpcs3.net/cdn/netplay/DefaultAvatar.png " , & avatar_url ) ;
break ;
}
case np_psn_status : : rpcn :
{
if ( ! is_psn_active )
break ;
2020-12-09 16:04:52 +01:00
2020-08-27 21:47:04 +02:00
// Connect RPCN client
if ( ! rpcn . connect ( g_cfg_rpcn . get_host ( ) ) )
{
rpcn_log . error ( " Connection to RPCN Failed! " ) ;
is_psn_active = false ;
return ;
}
if ( ! rpcn . login ( g_cfg_rpcn . get_npid ( ) , g_cfg_rpcn . get_password ( ) , g_cfg_rpcn . get_token ( ) ) )
{
rpcn_log . error ( " RPCN login attempt failed! " ) ;
is_psn_active = false ;
return ;
}
2021-01-20 07:59:41 +01:00
np_handler : : string_to_online_name ( rpcn . get_online_name ( ) , & online_name ) ;
np_handler : : string_to_avatar_url ( rpcn . get_avatar_url ( ) , & avatar_url ) ;
2020-08-27 21:47:04 +02:00
public_ip_addr = rpcn . get_addr_sig ( ) ;
2020-03-04 14:55:35 +01:00
break ;
}
default :
break ;
}
}
void np_handler : : terminate_NP ( )
{
// Reset memory pool
mpool . set ( 0 ) ;
mpool_size = 0 ;
mpool_avail = 0 ;
mpool_allocs . clear ( ) ;
2020-08-27 21:47:04 +02:00
if ( g_cfg . net . psn_status = = np_psn_status : : rpcn )
{
rpcn_log . error ( " Disconnecting from RPCN! " ) ;
rpcn . disconnect ( ) ;
}
2020-03-04 14:55:35 +01:00
}
vm : : addr_t np_handler : : allocate ( u32 size )
{
2020-11-10 09:55:49 +01:00
if ( ! size )
return vm : : cast ( static_cast < u64 > ( 0 ) ) ;
2020-03-04 14:55:35 +01:00
// Align allocs
2020-12-18 15:43:34 +01:00
const u32 alloc_size = utils : : align ( size , 4 ) ;
2020-03-04 14:55:35 +01:00
if ( alloc_size > mpool_avail )
{
sceNp . error ( " Not enough memory available in NP pool! " ) ;
return vm : : cast < u32 > ( 0 ) ;
}
u32 last_free = 0 ;
bool found_space = false ;
for ( auto & a : mpool_allocs )
{
if ( ( a . first - last_free ) > = alloc_size )
{
found_space = true ;
break ;
}
last_free = a . first + a . second ;
}
if ( ! found_space )
{
if ( ( mpool_size - last_free ) < alloc_size )
{
sceNp . error ( " Not enough memory available in NP pool(continuous block)! " ) ;
return vm : : cast < u32 > ( 0 ) ;
}
}
mpool_allocs . emplace ( last_free , alloc_size ) ;
mpool_avail - = alloc_size ;
memset ( ( static_cast < u8 * > ( mpool . get_ptr ( ) ) ) + last_free , 0 , alloc_size ) ;
2020-08-27 21:47:04 +02:00
sceNp . trace ( " Allocation off:%d size:%d psize:%d, pavail:%d " , last_free , alloc_size , mpool_size , mpool_avail ) ;
2020-03-04 14:55:35 +01:00
return vm : : cast ( mpool . addr ( ) + last_free ) ;
}
2020-08-27 21:47:04 +02:00
std : : vector < SceNpMatching2ServerId > np_handler : : get_match2_server_list ( SceNpMatching2ContextId ctx_id )
{
std : : vector < SceNpMatching2ServerId > server_list { } ;
2020-11-10 09:55:49 +01:00
if ( g_cfg . net . psn_status ! = np_psn_status : : rpcn )
2020-08-27 21:47:04 +02:00
{
2020-11-10 09:55:49 +01:00
return server_list ;
}
if ( ! rpcn . get_server_list ( get_req_id ( 0 ) , get_match2_context ( ctx_id ) - > communicationId , server_list ) )
{
rpcn_log . error ( " Disconnecting from RPCN! " ) ;
is_psn_active = false ;
2020-08-27 21:47:04 +02:00
}
return server_list ;
}
u32 np_handler : : get_server_status ( SceNpMatching2ContextId ctx_id , vm : : cptr < SceNpMatching2RequestOptParam > optParam , u16 server_id )
{
// TODO: actually implement interaction with server for this?
u32 req_id = generate_callback_info ( ctx_id , optParam ) ;
u32 event_key = get_event_key ( ) ;
SceNpMatching2GetServerInfoResponse * serv_info = reinterpret_cast < SceNpMatching2GetServerInfoResponse * > ( allocate_req_result ( event_key , sizeof ( SceNpMatching2GetServerInfoResponse ) ) ) ;
serv_info - > server . serverId = server_id ;
serv_info - > server . status = SCE_NP_MATCHING2_SERVER_STATUS_AVAILABLE ;
const auto cb_info = std : : move ( pending_requests . at ( req_id ) ) ;
pending_requests . erase ( req_id ) ;
2021-03-02 12:59:19 +01:00
sysutil_register_cb ( [ = ] ( ppu_thread & cb_ppu ) - > s32
{
2020-08-27 21:47:04 +02:00
cb_info . cb ( cb_ppu , cb_info . ctx_id , req_id , SCE_NP_MATCHING2_REQUEST_EVENT_GetServerInfo , event_key , 0 , sizeof ( SceNpMatching2GetServerInfoResponse ) , cb_info . cb_arg ) ;
return 0 ;
} ) ;
return req_id ;
}
2021-03-05 20:05:37 +01:00
u32 np_handler : : create_server_context ( SceNpMatching2ContextId ctx_id , vm : : cptr < SceNpMatching2RequestOptParam > optParam , u16 /*server_id*/ )
2020-08-27 21:47:04 +02:00
{
u32 req_id = generate_callback_info ( ctx_id , optParam ) ;
u32 event_key = get_event_key ( ) ;
const auto cb_info = std : : move ( pending_requests . at ( req_id ) ) ;
pending_requests . erase ( req_id ) ;
2021-03-02 12:59:19 +01:00
sysutil_register_cb ( [ = ] ( ppu_thread & cb_ppu ) - > s32
{
2020-08-27 21:47:04 +02:00
cb_info . cb ( cb_ppu , cb_info . ctx_id , req_id , SCE_NP_MATCHING2_REQUEST_EVENT_CreateServerContext , event_key , 0 , 0 , cb_info . cb_arg ) ;
return 0 ;
} ) ;
return req_id ;
}
u32 np_handler : : get_world_list ( SceNpMatching2ContextId ctx_id , vm : : cptr < SceNpMatching2RequestOptParam > optParam , u16 server_id )
{
u32 req_id = generate_callback_info ( ctx_id , optParam ) ;
2020-11-10 09:55:49 +01:00
if ( ! rpcn . get_world_list ( req_id , get_match2_context ( ctx_id ) - > communicationId , server_id ) )
2020-08-27 21:47:04 +02:00
{
rpcn_log . error ( " Disconnecting from RPCN! " ) ;
is_psn_active = false ;
}
return req_id ;
}
u32 np_handler : : create_join_room ( SceNpMatching2ContextId ctx_id , vm : : cptr < SceNpMatching2RequestOptParam > optParam , const SceNpMatching2CreateJoinRoomRequest * req )
{
u32 req_id = generate_callback_info ( ctx_id , optParam ) ;
2020-11-10 09:55:49 +01:00
if ( ! rpcn . createjoin_room ( req_id , get_match2_context ( ctx_id ) - > communicationId , req ) )
2020-08-27 21:47:04 +02:00
{
rpcn_log . error ( " Disconnecting from RPCN! " ) ;
is_psn_active = false ;
}
return req_id ;
}
u32 np_handler : : join_room ( SceNpMatching2ContextId ctx_id , vm : : cptr < SceNpMatching2RequestOptParam > optParam , const SceNpMatching2JoinRoomRequest * req )
{
u32 req_id = generate_callback_info ( ctx_id , optParam ) ;
2020-11-10 09:55:49 +01:00
if ( ! rpcn . join_room ( req_id , get_match2_context ( ctx_id ) - > communicationId , req ) )
2020-08-27 21:47:04 +02:00
{
rpcn_log . error ( " Disconnecting from RPCN! " ) ;
is_psn_active = false ;
}
return req_id ;
}
u32 np_handler : : leave_room ( SceNpMatching2ContextId ctx_id , vm : : cptr < SceNpMatching2RequestOptParam > optParam , const SceNpMatching2LeaveRoomRequest * req )
{
u32 req_id = generate_callback_info ( ctx_id , optParam ) ;
2020-11-10 09:55:49 +01:00
if ( ! rpcn . leave_room ( req_id , get_match2_context ( ctx_id ) - > communicationId , req ) )
2020-08-27 21:47:04 +02:00
{
rpcn_log . error ( " Disconnecting from RPCN! " ) ;
is_psn_active = false ;
}
return req_id ;
}
u32 np_handler : : search_room ( SceNpMatching2ContextId ctx_id , vm : : cptr < SceNpMatching2RequestOptParam > optParam , const SceNpMatching2SearchRoomRequest * req )
{
u32 req_id = generate_callback_info ( ctx_id , optParam ) ;
2020-11-10 09:55:49 +01:00
if ( ! rpcn . search_room ( req_id , get_match2_context ( ctx_id ) - > communicationId , req ) )
2020-08-27 21:47:04 +02:00
{
rpcn_log . error ( " Disconnecting from RPCN! " ) ;
is_psn_active = false ;
}
return req_id ;
}
u32 np_handler : : set_roomdata_external ( SceNpMatching2ContextId ctx_id , vm : : cptr < SceNpMatching2RequestOptParam > optParam , const SceNpMatching2SetRoomDataExternalRequest * req )
{
u32 req_id = generate_callback_info ( ctx_id , optParam ) ;
extra_nps : : print_set_roomdata_ext_req ( req ) ;
2020-11-10 09:55:49 +01:00
if ( ! rpcn . set_roomdata_external ( req_id , get_match2_context ( ctx_id ) - > communicationId , req ) )
2020-08-27 21:47:04 +02:00
{
rpcn_log . error ( " Disconnecting from RPCN! " ) ;
is_psn_active = false ;
}
return req_id ;
}
u32 np_handler : : get_roomdata_internal ( SceNpMatching2ContextId ctx_id , vm : : cptr < SceNpMatching2RequestOptParam > optParam , const SceNpMatching2GetRoomDataInternalRequest * req )
{
u32 req_id = generate_callback_info ( ctx_id , optParam ) ;
2020-11-10 09:55:49 +01:00
if ( ! rpcn . get_roomdata_internal ( req_id , get_match2_context ( ctx_id ) - > communicationId , req ) )
2020-08-27 21:47:04 +02:00
{
rpcn_log . error ( " Disconnecting from RPCN! " ) ;
is_psn_active = false ;
}
return req_id ;
}
u32 np_handler : : set_roomdata_internal ( SceNpMatching2ContextId ctx_id , vm : : cptr < SceNpMatching2RequestOptParam > optParam , const SceNpMatching2SetRoomDataInternalRequest * req )
{
u32 req_id = generate_callback_info ( ctx_id , optParam ) ;
extra_nps : : print_set_roomdata_int_req ( req ) ;
2020-11-10 09:55:49 +01:00
if ( ! rpcn . set_roomdata_internal ( req_id , get_match2_context ( ctx_id ) - > communicationId , req ) )
2020-08-27 21:47:04 +02:00
{
rpcn_log . error ( " Disconnecting from RPCN! " ) ;
is_psn_active = false ;
}
return req_id ;
}
u32 np_handler : : get_ping_info ( SceNpMatching2ContextId ctx_id , vm : : cptr < SceNpMatching2RequestOptParam > optParam , const SceNpMatching2SignalingGetPingInfoRequest * req )
{
u32 req_id = generate_callback_info ( ctx_id , optParam ) ;
2020-11-10 09:55:49 +01:00
if ( ! rpcn . ping_room_owner ( req_id , get_match2_context ( ctx_id ) - > communicationId , req - > roomId ) )
2020-08-27 21:47:04 +02:00
{
rpcn_log . error ( " Disconnecting from RPCN! " ) ;
is_psn_active = false ;
}
return req_id ;
}
u32 np_handler : : send_room_message ( SceNpMatching2ContextId ctx_id , vm : : cptr < SceNpMatching2RequestOptParam > optParam , const SceNpMatching2SendRoomMessageRequest * req )
{
u32 req_id = generate_callback_info ( ctx_id , optParam ) ;
2020-11-10 09:55:49 +01:00
if ( ! rpcn . send_room_message ( req_id , get_match2_context ( ctx_id ) - > communicationId , req ) )
2020-08-27 21:47:04 +02:00
{
rpcn_log . error ( " Disconnecting from RPCN! " ) ;
is_psn_active = false ;
}
return req_id ;
}
2020-09-07 23:50:17 +02:00
void np_handler : : req_sign_infos ( const std : : string & npid , u32 conn_id )
{
u32 req_id = get_req_id ( 0x3333 ) ;
pending_sign_infos_requests [ req_id ] = conn_id ;
if ( ! rpcn . req_sign_infos ( req_id , npid ) )
{
rpcn_log . error ( " Disconnecting from RPCN! " ) ;
is_psn_active = false ;
}
return ;
}
2021-03-05 20:05:37 +01:00
void np_handler : : req_ticket ( u32 /*version*/ , const SceNpId * /*npid*/ , const char * service_id , const u8 * /*cookie*/ , u32 /*cookie_size*/ , const char * /*entitlement_id*/ , u32 /*consumed_count*/ )
2020-09-07 23:50:17 +02:00
{
u32 req_id = get_req_id ( 0x3333 ) ;
std : : string service_id_str ( service_id ) ;
if ( ! rpcn . req_ticket ( req_id , service_id_str ) )
{
rpcn_log . error ( " Disconnecting from RPCN! " ) ;
is_psn_active = false ;
}
return ;
}
2020-08-27 21:47:04 +02:00
u32 np_handler : : get_match2_event ( SceNpMatching2EventKey event_key , u8 * dest , u32 size )
{
std : : lock_guard lock ( mutex_req_results ) ;
if ( ! match2_req_results . count ( event_key ) )
return 0 ;
u32 size_copied = std : : min ( size , static_cast < u32 > ( match2_req_results . at ( event_key ) . size ( ) ) ) ;
memcpy ( dest , match2_req_results . at ( event_key ) . data ( ) , size_copied ) ;
return size_copied ;
}
2020-03-04 14:55:35 +01:00
void np_handler : : operator ( ) ( )
{
2020-08-27 21:47:04 +02:00
if ( g_cfg . net . psn_status ! = np_psn_status : : rpcn )
return ;
while ( thread_ctrl : : state ( ) ! = thread_state : : aborting & & ! Emu . IsStopped ( ) )
{
if ( ! rpcn . manage_connection ( ) )
{
2021-02-21 14:43:02 +01:00
thread_ctrl : : wait_for ( 200'000 ) ;
2020-08-27 21:47:04 +02:00
continue ;
}
auto replies = rpcn . get_replies ( ) ;
for ( auto & reply : replies )
{
const u16 command = reply . second . first ;
const u32 req_id = reply . first ;
std : : vector < u8 > & data = reply . second . second ;
switch ( command )
{
case CommandType : : GetWorldList : reply_get_world_list ( req_id , data ) ; break ;
case CommandType : : CreateRoom : reply_create_join_room ( req_id , data ) ; break ;
case CommandType : : JoinRoom : reply_join_room ( req_id , data ) ; break ;
case CommandType : : LeaveRoom : reply_leave_room ( req_id , data ) ; break ;
case CommandType : : SearchRoom : reply_search_room ( req_id , data ) ; break ;
case CommandType : : SetRoomDataExternal : reply_set_roomdata_external ( req_id , data ) ; break ;
case CommandType : : GetRoomDataInternal : reply_get_roomdata_internal ( req_id , data ) ; break ;
case CommandType : : SetRoomDataInternal : reply_set_roomdata_internal ( req_id , data ) ; break ;
case CommandType : : PingRoomOwner : reply_get_ping_info ( req_id , data ) ; break ;
case CommandType : : SendRoomMessage : reply_send_room_message ( req_id , data ) ; break ;
2020-09-07 23:50:17 +02:00
case CommandType : : RequestSignalingInfos : reply_req_sign_infos ( req_id , data ) ; break ;
case CommandType : : RequestTicket : reply_req_ticket ( req_id , data ) ; break ;
2020-08-27 21:47:04 +02:00
default : rpcn_log . error ( " Unknown reply(%d) received! " , command ) ; break ;
}
}
auto notifications = rpcn . get_notifications ( ) ;
for ( auto & notif : notifications )
{
switch ( notif . first )
{
case NotificationType : : UserJoinedRoom : notif_user_joined_room ( notif . second ) ; break ;
case NotificationType : : UserLeftRoom : notif_user_left_room ( notif . second ) ; break ;
case NotificationType : : RoomDestroyed : notif_room_destroyed ( notif . second ) ; break ;
2020-09-07 23:50:17 +02:00
case NotificationType : : SignalP2PConnect : notif_p2p_connect ( notif . second ) ; break ;
2020-08-27 21:47:04 +02:00
case NotificationType : : RoomMessageReceived : notif_room_message_received ( notif . second ) ; break ;
default : rpcn_log . error ( " Unknown notification(%d) received! " , notif . first ) ; break ;
}
}
}
2020-03-04 14:55:35 +01:00
}
2020-08-27 21:47:04 +02:00
bool np_handler : : reply_get_world_list ( u32 req_id , std : : vector < u8 > & reply_data )
2020-03-04 14:55:35 +01:00
{
2020-08-27 21:47:04 +02:00
if ( pending_requests . count ( req_id ) = = 0 )
return error_and_disconnect ( " Unexpected reply ID to GetWorldList " ) ;
const auto cb_info = std : : move ( pending_requests . at ( req_id ) ) ;
pending_requests . erase ( req_id ) ;
vec_stream reply ( reply_data , 1 ) ;
std : : vector < u32 > world_list ;
u32 num_worlds = reply . get < u32 > ( ) ;
for ( u32 i = 0 ; i < num_worlds ; i + + )
{
world_list . push_back ( reply . get < u32 > ( ) ) ;
}
if ( reply . is_error ( ) )
{
world_list . clear ( ) ;
return error_and_disconnect ( " Malformed reply to GetWorldList command " ) ;
}
u32 event_key = get_event_key ( ) ;
SceNpMatching2GetWorldInfoListResponse * world_info = reinterpret_cast < SceNpMatching2GetWorldInfoListResponse * > ( allocate_req_result ( event_key , sizeof ( SceNpMatching2GetWorldInfoListResponse ) ) ) ;
world_info - > worldNum = world_list . size ( ) ;
if ( ! world_list . empty ( ) )
{
world_info - > world . set ( allocate ( sizeof ( SceNpMatching2World ) * world_list . size ( ) ) ) ;
2020-12-18 08:39:54 +01:00
for ( usz i = 0 ; i < world_list . size ( ) ; i + + )
2020-08-27 21:47:04 +02:00
{
world_info - > world [ i ] . worldId = world_list [ i ] ;
world_info - > world [ i ] . numOfLobby = 1 ; // TODO
world_info - > world [ i ] . maxNumOfTotalLobbyMember = 10000 ;
world_info - > world [ i ] . curNumOfTotalLobbyMember = 1 ;
world_info - > world [ i ] . curNumOfRoom = 1 ;
world_info - > world [ i ] . curNumOfTotalRoomMember = 1 ;
}
}
2021-03-02 12:59:19 +01:00
sysutil_register_cb ( [ = ] ( ppu_thread & cb_ppu ) - > s32
{
2020-08-27 21:47:04 +02:00
cb_info . cb ( cb_ppu , cb_info . ctx_id , req_id , SCE_NP_MATCHING2_REQUEST_EVENT_GetWorldInfoList , event_key , 0 , sizeof ( SceNpMatching2GetWorldInfoListResponse ) , cb_info . cb_arg ) ;
return 0 ;
} ) ;
return true ;
2020-03-04 14:55:35 +01:00
}
2020-08-27 21:47:04 +02:00
bool np_handler : : reply_create_join_room ( u32 req_id , std : : vector < u8 > & reply_data )
2020-03-04 14:55:35 +01:00
{
2020-08-27 21:47:04 +02:00
if ( pending_requests . count ( req_id ) = = 0 )
return error_and_disconnect ( " Unexpected reply ID to CreateRoom " ) ;
const auto cb_info = std : : move ( pending_requests . at ( req_id ) ) ;
pending_requests . erase ( req_id ) ;
vec_stream reply ( reply_data , 1 ) ;
auto create_room_resp = reply . get_rawdata ( ) ;
if ( reply . is_error ( ) )
return error_and_disconnect ( " Malformed reply to CreateRoom command " ) ;
u32 event_key = get_event_key ( ) ;
auto resp = flatbuffers : : GetRoot < RoomDataInternal > ( create_room_resp . data ( ) ) ;
SceNpMatching2CreateJoinRoomResponse * room_resp = reinterpret_cast < SceNpMatching2CreateJoinRoomResponse * > ( allocate_req_result ( event_key , sizeof ( SceNpMatching2CreateJoinRoomResponse ) ) ) ;
vm : : ptr < SceNpMatching2RoomDataInternal > room_info ( allocate ( sizeof ( SceNpMatching2RoomDataInternal ) ) ) ;
room_resp - > roomDataInternal = room_info ;
RoomDataInternal_to_SceNpMatching2RoomDataInternal ( resp , room_info . get_ptr ( ) , npid ) ;
2020-09-07 23:50:17 +02:00
// Establish Matching2 self signaling info
2021-03-02 12:59:19 +01:00
auto & sigh = g_fxo - > get < named_thread < signaling_handler > > ( ) ;
sigh . set_self_sig2_info ( room_info - > roomId , 1 ) ;
sigh . set_sig2_infos ( room_info - > roomId , 1 , SCE_NP_SIGNALING_CONN_STATUS_ACTIVE , rpcn . get_addr_sig ( ) , rpcn . get_port_sig ( ) , true ) ;
2020-09-07 23:50:17 +02:00
// TODO? Should this send a message to Signaling CB? Is this even necessary?
2020-08-27 21:47:04 +02:00
extra_nps : : print_create_room_resp ( room_resp ) ;
2021-03-02 12:59:19 +01:00
sysutil_register_cb ( [ = ] ( ppu_thread & cb_ppu ) - > s32
{
2020-08-27 21:47:04 +02:00
cb_info . cb ( cb_ppu , cb_info . ctx_id , req_id , SCE_NP_MATCHING2_REQUEST_EVENT_CreateJoinRoom , event_key , 0 , sizeof ( SceNpMatching2CreateJoinRoomResponse ) , cb_info . cb_arg ) ;
return 0 ;
} ) ;
return true ;
}
bool np_handler : : reply_join_room ( u32 req_id , std : : vector < u8 > & reply_data )
{
if ( pending_requests . count ( req_id ) = = 0 )
return error_and_disconnect ( " Unexpected reply ID to JoinRoom " ) ;
const auto cb_info = std : : move ( pending_requests . at ( req_id ) ) ;
pending_requests . erase ( req_id ) ;
vec_stream reply ( reply_data , 1 ) ;
auto join_room_resp = reply . get_rawdata ( ) ;
if ( reply . is_error ( ) )
return error_and_disconnect ( " Malformed reply to JoinRoom command " ) ;
u32 event_key = get_event_key ( ) ;
auto resp = flatbuffers : : GetRoot < RoomDataInternal > ( join_room_resp . data ( ) ) ;
SceNpMatching2JoinRoomResponse * room_resp = reinterpret_cast < SceNpMatching2JoinRoomResponse * > ( allocate_req_result ( event_key , sizeof ( SceNpMatching2JoinRoomResponse ) ) ) ;
vm : : ptr < SceNpMatching2RoomDataInternal > room_info ( allocate ( sizeof ( SceNpMatching2RoomDataInternal ) ) ) ;
room_resp - > roomDataInternal = room_info ;
u16 member_id = RoomDataInternal_to_SceNpMatching2RoomDataInternal ( resp , room_info . get_ptr ( ) , npid ) ;
extra_nps : : print_room_data_internal ( room_resp - > roomDataInternal . get_ptr ( ) ) ;
2020-09-07 23:50:17 +02:00
// Establish Matching2 self signaling info
2021-03-02 12:59:19 +01:00
auto & sigh = g_fxo - > get < named_thread < signaling_handler > > ( ) ;
sigh . set_self_sig2_info ( room_info - > roomId , member_id ) ;
sigh . set_sig2_infos ( room_info - > roomId , member_id , SCE_NP_SIGNALING_CONN_STATUS_ACTIVE , rpcn . get_addr_sig ( ) , rpcn . get_port_sig ( ) , true ) ;
2020-09-07 23:50:17 +02:00
// TODO? Should this send a message to Signaling CB? Is this even necessary?
2020-08-27 21:47:04 +02:00
2021-03-02 12:59:19 +01:00
sysutil_register_cb ( [ = ] ( ppu_thread & cb_ppu ) - > s32
{
2020-08-27 21:47:04 +02:00
cb_info . cb ( cb_ppu , cb_info . ctx_id , req_id , SCE_NP_MATCHING2_REQUEST_EVENT_JoinRoom , event_key , 0 , sizeof ( SceNpMatching2JoinRoomResponse ) , cb_info . cb_arg ) ;
return 0 ;
} ) ;
return true ;
2020-03-04 14:55:35 +01:00
}
2020-08-27 21:47:04 +02:00
bool np_handler : : reply_leave_room ( u32 req_id , std : : vector < u8 > & reply_data )
2020-03-04 14:55:35 +01:00
{
2020-08-27 21:47:04 +02:00
if ( pending_requests . count ( req_id ) = = 0 )
return error_and_disconnect ( " Unexpected reply ID to LeaveRoom " ) ;
const auto cb_info = std : : move ( pending_requests . at ( req_id ) ) ;
pending_requests . erase ( req_id ) ;
vec_stream reply ( reply_data , 1 ) ;
u64 room_id = reply . get < u64 > ( ) ;
if ( reply . is_error ( ) )
return error_and_disconnect ( " Malformed reply to LeaveRoom command " ) ;
u32 event_key = get_event_key ( ) ; // Unsure if necessary if there is no data
2020-09-07 23:50:17 +02:00
// Disconnect all users from that room
2021-03-02 12:59:19 +01:00
auto & sigh = g_fxo - > get < named_thread < signaling_handler > > ( ) ;
sigh . disconnect_sig2_users ( room_id ) ;
2020-08-27 21:47:04 +02:00
2021-03-02 12:59:19 +01:00
sysutil_register_cb ( [ = ] ( ppu_thread & cb_ppu ) - > s32
{
2020-08-27 21:47:04 +02:00
cb_info . cb ( cb_ppu , cb_info . ctx_id , req_id , SCE_NP_MATCHING2_REQUEST_EVENT_LeaveRoom , event_key , 0 , 0 , cb_info . cb_arg ) ;
return 0 ;
} ) ;
return true ;
2020-03-04 14:55:35 +01:00
}
2020-08-27 21:47:04 +02:00
bool np_handler : : reply_search_room ( u32 req_id , std : : vector < u8 > & reply_data )
2020-03-04 14:55:35 +01:00
{
2020-08-27 21:47:04 +02:00
if ( pending_requests . count ( req_id ) = = 0 )
return error_and_disconnect ( " Unexpected reply ID to SearchRoom " ) ;
const auto cb_info = std : : move ( pending_requests . at ( req_id ) ) ;
pending_requests . erase ( req_id ) ;
vec_stream reply ( reply_data , 1 ) ;
auto search_room_resp = reply . get_rawdata ( ) ;
if ( reply . is_error ( ) )
return error_and_disconnect ( " Malformed reply to SearchRoom command " ) ;
u32 event_key = get_event_key ( ) ;
auto resp = flatbuffers : : GetRoot < SearchRoomResponse > ( search_room_resp . data ( ) ) ;
SceNpMatching2SearchRoomResponse * search_resp = reinterpret_cast < SceNpMatching2SearchRoomResponse * > ( allocate_req_result ( event_key , sizeof ( SceNpMatching2SearchRoomResponse ) ) ) ;
SearchRoomReponse_to_SceNpMatching2SearchRoomResponse ( resp , search_resp ) ;
2021-03-02 12:59:19 +01:00
sysutil_register_cb ( [ = ] ( ppu_thread & cb_ppu ) - > s32
{
2020-08-27 21:47:04 +02:00
cb_info . cb ( cb_ppu , cb_info . ctx_id , req_id , SCE_NP_MATCHING2_REQUEST_EVENT_SearchRoom , event_key , 0 , sizeof ( SceNpMatching2SearchRoomResponse ) , cb_info . cb_arg ) ;
return 0 ;
} ) ;
return true ;
2020-03-04 14:55:35 +01:00
}
2021-03-05 20:05:37 +01:00
bool np_handler : : reply_set_roomdata_external ( u32 req_id , std : : vector < u8 > & /*reply_data*/ )
2020-03-04 14:55:35 +01:00
{
2020-08-27 21:47:04 +02:00
if ( pending_requests . count ( req_id ) = = 0 )
return error_and_disconnect ( " Unexpected reply ID to SetRoomDataExternal " ) ;
const auto cb_info = std : : move ( pending_requests . at ( req_id ) ) ;
pending_requests . erase ( req_id ) ;
u32 event_key = get_event_key ( ) ; // Unsure if necessary if there is no data
2021-03-02 12:59:19 +01:00
sysutil_register_cb ( [ = ] ( ppu_thread & cb_ppu ) - > s32
{
2020-08-27 21:47:04 +02:00
cb_info . cb ( cb_ppu , cb_info . ctx_id , req_id , SCE_NP_MATCHING2_REQUEST_EVENT_SetRoomDataExternal , event_key , 0 , 0 , cb_info . cb_arg ) ;
return 0 ;
} ) ;
return true ;
2020-03-04 14:55:35 +01:00
}
2020-08-27 21:47:04 +02:00
bool np_handler : : reply_get_roomdata_internal ( u32 req_id , std : : vector < u8 > & reply_data )
2020-03-04 14:55:35 +01:00
{
2020-08-27 21:47:04 +02:00
if ( pending_requests . count ( req_id ) = = 0 )
return error_and_disconnect ( " Unexpected reply ID to GetRoomDataInternal " ) ;
const auto cb_info = std : : move ( pending_requests . at ( req_id ) ) ;
pending_requests . erase ( req_id ) ;
vec_stream reply ( reply_data , 1 ) ;
auto internal_data = reply . get_rawdata ( ) ;
if ( reply . is_error ( ) )
return error_and_disconnect ( " Malformed reply to GetRoomDataInternal command " ) ;
u32 event_key = get_event_key ( ) ;
auto resp = flatbuffers : : GetRoot < RoomDataInternal > ( internal_data . data ( ) ) ;
SceNpMatching2GetRoomDataInternalResponse * room_resp = reinterpret_cast < SceNpMatching2GetRoomDataInternalResponse * > ( allocate_req_result ( event_key , sizeof ( SceNpMatching2GetRoomDataInternalResponse ) ) ) ;
vm : : ptr < SceNpMatching2RoomDataInternal > room_info ( allocate ( sizeof ( SceNpMatching2RoomDataInternal ) ) ) ;
room_resp - > roomDataInternal = room_info ;
RoomDataInternal_to_SceNpMatching2RoomDataInternal ( resp , room_info . get_ptr ( ) , npid ) ;
extra_nps : : print_room_data_internal ( room_resp - > roomDataInternal . get_ptr ( ) ) ;
2021-03-02 12:59:19 +01:00
sysutil_register_cb ( [ = ] ( ppu_thread & cb_ppu ) - > s32
{
2020-08-27 21:47:04 +02:00
cb_info . cb ( cb_ppu , cb_info . ctx_id , req_id , SCE_NP_MATCHING2_REQUEST_EVENT_GetRoomDataInternal , event_key , 0 , sizeof ( SceNpMatching2GetRoomDataInternalResponse ) , cb_info . cb_arg ) ;
return 0 ;
} ) ;
return true ;
2020-03-04 14:55:35 +01:00
}
2021-03-05 20:05:37 +01:00
bool np_handler : : reply_set_roomdata_internal ( u32 req_id , std : : vector < u8 > & /*reply_data*/ )
2020-03-04 14:55:35 +01:00
{
2020-08-27 21:47:04 +02:00
if ( pending_requests . count ( req_id ) = = 0 )
return error_and_disconnect ( " Unexpected reply ID to SetRoomDataInternal " ) ;
const auto cb_info = std : : move ( pending_requests . at ( req_id ) ) ;
pending_requests . erase ( req_id ) ;
u32 event_key = get_event_key ( ) ; // Unsure if necessary if there is no data
2021-03-02 12:59:19 +01:00
sysutil_register_cb ( [ = ] ( ppu_thread & cb_ppu ) - > s32
{
2020-08-27 21:47:04 +02:00
cb_info . cb ( cb_ppu , cb_info . ctx_id , req_id , SCE_NP_MATCHING2_REQUEST_EVENT_SetRoomDataInternal , event_key , 0 , 0 , cb_info . cb_arg ) ;
return 0 ;
} ) ;
return true ;
2020-03-04 14:55:35 +01:00
}
2020-08-27 21:47:04 +02:00
bool np_handler : : reply_get_ping_info ( u32 req_id , std : : vector < u8 > & reply_data )
2020-03-04 14:55:35 +01:00
{
2020-08-27 21:47:04 +02:00
if ( pending_requests . count ( req_id ) = = 0 )
return error_and_disconnect ( " Unexpected reply ID to PingRoomOwner " ) ;
const auto cb_info = std : : move ( pending_requests . at ( req_id ) ) ;
pending_requests . erase ( req_id ) ;
vec_stream reply ( reply_data , 1 ) ;
auto ping_resp = reply . get_rawdata ( ) ;
if ( reply . is_error ( ) )
return error_and_disconnect ( " Malformed reply to PingRoomOwner command " ) ;
u32 event_key = get_event_key ( ) ;
auto resp = flatbuffers : : GetRoot < GetPingInfoResponse > ( ping_resp . data ( ) ) ;
SceNpMatching2SignalingGetPingInfoResponse * final_ping_resp = reinterpret_cast < SceNpMatching2SignalingGetPingInfoResponse * > ( allocate_req_result ( event_key , sizeof ( SceNpMatching2SignalingGetPingInfoResponse ) ) ) ;
GetPingInfoResponse_to_SceNpMatching2SignalingGetPingInfoResponse ( resp , final_ping_resp ) ;
2021-03-02 12:59:19 +01:00
sysutil_register_cb ( [ = ] ( ppu_thread & cb_ppu ) - > s32
{
2020-08-27 21:47:04 +02:00
cb_info . cb ( cb_ppu , cb_info . ctx_id , req_id , SCE_NP_MATCHING2_REQUEST_EVENT_SignalingGetPingInfo , event_key , 0 , sizeof ( SceNpMatching2SignalingGetPingInfoResponse ) , cb_info . cb_arg ) ;
return 0 ;
} ) ;
return true ;
}
2021-03-05 20:05:37 +01:00
bool np_handler : : reply_send_room_message ( u32 req_id , std : : vector < u8 > & /*reply_data*/ )
2020-08-27 21:47:04 +02:00
{
if ( pending_requests . count ( req_id ) = = 0 )
return error_and_disconnect ( " Unexpected reply ID to PingRoomOwner " ) ;
const auto cb_info = std : : move ( pending_requests . at ( req_id ) ) ;
pending_requests . erase ( req_id ) ;
2021-03-02 12:59:19 +01:00
sysutil_register_cb ( [ = ] ( ppu_thread & cb_ppu ) - > s32
{
2020-08-27 21:47:04 +02:00
cb_info . cb ( cb_ppu , cb_info . ctx_id , req_id , SCE_NP_MATCHING2_REQUEST_EVENT_SendRoomMessage , 0 , 0 , 0 , cb_info . cb_arg ) ;
return 0 ;
} ) ;
return true ;
2020-09-07 23:50:17 +02:00
}
bool np_handler : : reply_req_sign_infos ( u32 req_id , std : : vector < u8 > & reply_data )
{
if ( ! pending_sign_infos_requests . count ( req_id ) )
return error_and_disconnect ( " Unexpected reply ID to req RequestSignalingInfos " ) ;
2020-12-09 16:04:52 +01:00
2020-09-07 23:50:17 +02:00
u32 conn_id = pending_sign_infos_requests . at ( req_id ) ;
pending_sign_infos_requests . erase ( req_id ) ;
vec_stream reply ( reply_data , 1 ) ;
u32 addr = reply . get < u32 > ( ) ;
u16 port = reply . get < u16 > ( ) ;
if ( reply . is_error ( ) )
return error_and_disconnect ( " Malformed reply to RequestSignalingInfos command " ) ;
2020-12-09 16:04:52 +01:00
2021-03-02 12:59:19 +01:00
auto & sigh = g_fxo - > get < named_thread < signaling_handler > > ( ) ;
sigh . start_sig ( conn_id , addr , port ) ;
2020-09-07 23:50:17 +02:00
return true ;
}
2021-03-05 20:05:37 +01:00
bool np_handler : : reply_req_ticket ( u32 /*req_id*/ , std : : vector < u8 > & reply_data )
2020-09-07 23:50:17 +02:00
{
vec_stream reply ( reply_data , 1 ) ;
auto ticket_raw = reply . get_rawdata ( ) ;
if ( reply . is_error ( ) )
return error_and_disconnect ( " Malformed reply to RequestTicket command " ) ;
2020-12-09 16:04:52 +01:00
2020-09-07 23:50:17 +02:00
current_ticket = std : : move ( ticket_raw ) ;
auto ticket_size = static_cast < s32 > ( current_ticket . size ( ) ) ;
2020-08-27 21:47:04 +02:00
2020-09-07 23:50:17 +02:00
if ( manager_cb )
{
sysutil_register_cb ( [ manager_cb = this - > manager_cb , ticket_size , manager_cb_arg = this - > manager_cb_arg ] ( ppu_thread & cb_ppu ) - > s32
{
manager_cb ( cb_ppu , SCE_NP_MANAGER_EVENT_GOT_TICKET , ticket_size , manager_cb_arg ) ;
return 0 ;
} ) ;
}
return true ;
2020-08-27 21:47:04 +02:00
}
void np_handler : : notif_user_joined_room ( std : : vector < u8 > & data )
{
vec_stream noti ( data ) ;
u64 room_id = noti . get < u64 > ( ) ;
auto update_info_raw = noti . get_rawdata ( ) ;
if ( noti . is_error ( ) )
{
rpcn_log . error ( " Received faulty UserJoinedRoom notification " ) ;
return ;
}
u32 event_key = get_event_key ( ) ;
auto update_info = flatbuffers : : GetRoot < RoomMemberUpdateInfo > ( update_info_raw . data ( ) ) ;
SceNpMatching2RoomMemberUpdateInfo * notif_data = reinterpret_cast < SceNpMatching2RoomMemberUpdateInfo * > ( allocate_req_result ( event_key , sizeof ( SceNpMatching2RoomMemberUpdateInfo ) ) ) ;
RoomMemberUpdateInfo_to_SceNpMatching2RoomMemberUpdateInfo ( update_info , notif_data ) ;
2020-09-23 20:12:42 +02:00
rpcn_log . notice ( " Received notification that user %s(%d) joined the room(%d) " , notif_data - > roomMemberDataInternal - > userInfo . npId . handle . data , notif_data - > roomMemberDataInternal - > memberId , room_id ) ;
2020-09-07 23:50:17 +02:00
extra_nps : : print_room_member_data_internal ( notif_data - > roomMemberDataInternal . get_ptr ( ) ) ;
2021-03-02 12:59:19 +01:00
sysutil_register_cb ( [ room_event_cb = this - > room_event_cb , room_id , event_key , room_event_cb_ctx = this - > room_event_cb_ctx , room_event_cb_arg = this - > room_event_cb_arg ] ( ppu_thread & cb_ppu ) - > s32
{
2020-08-27 21:47:04 +02:00
room_event_cb ( cb_ppu , room_event_cb_ctx , room_id , SCE_NP_MATCHING2_ROOM_EVENT_MemberJoined , event_key , 0 , sizeof ( SceNpMatching2RoomMemberUpdateInfo ) , room_event_cb_arg ) ;
return 0 ;
} ) ;
}
void np_handler : : notif_user_left_room ( std : : vector < u8 > & data )
{
vec_stream noti ( data ) ;
u64 room_id = noti . get < u64 > ( ) ;
auto update_info_raw = noti . get_rawdata ( ) ;
if ( noti . is_error ( ) )
{
rpcn_log . error ( " Received faulty UserLeftRoom notification " ) ;
return ;
}
u32 event_key = get_event_key ( ) ;
auto update_info = flatbuffers : : GetRoot < RoomMemberUpdateInfo > ( update_info_raw . data ( ) ) ;
SceNpMatching2RoomMemberUpdateInfo * notif_data = reinterpret_cast < SceNpMatching2RoomMemberUpdateInfo * > ( allocate_req_result ( event_key , sizeof ( SceNpMatching2RoomMemberUpdateInfo ) ) ) ;
RoomMemberUpdateInfo_to_SceNpMatching2RoomMemberUpdateInfo ( update_info , notif_data ) ;
2020-09-23 20:12:42 +02:00
rpcn_log . notice ( " Received notification that user %s(%d) left the room(%d) " , notif_data - > roomMemberDataInternal - > userInfo . npId . handle . data , notif_data - > roomMemberDataInternal - > memberId , room_id ) ;
2020-09-07 23:50:17 +02:00
extra_nps : : print_room_member_data_internal ( notif_data - > roomMemberDataInternal . get_ptr ( ) ) ;
2021-03-02 12:59:19 +01:00
sysutil_register_cb ( [ room_event_cb = this - > room_event_cb , room_event_cb_ctx = this - > room_event_cb_ctx , room_id , event_key , room_event_cb_arg = this - > room_event_cb_arg ] ( ppu_thread & cb_ppu ) - > s32
{
2020-08-27 21:47:04 +02:00
room_event_cb ( cb_ppu , room_event_cb_ctx , room_id , SCE_NP_MATCHING2_ROOM_EVENT_MemberLeft , event_key , 0 , sizeof ( SceNpMatching2RoomMemberUpdateInfo ) , room_event_cb_arg ) ;
return 0 ;
} ) ;
}
void np_handler : : notif_room_destroyed ( std : : vector < u8 > & data )
{
vec_stream noti ( data ) ;
u64 room_id = noti . get < u64 > ( ) ;
auto update_info_raw = noti . get_rawdata ( ) ;
if ( noti . is_error ( ) )
{
rpcn_log . error ( " Received faulty RoomDestroyed notification " ) ;
return ;
}
u32 event_key = get_event_key ( ) ;
auto update_info = flatbuffers : : GetRoot < RoomUpdateInfo > ( update_info_raw . data ( ) ) ;
SceNpMatching2RoomUpdateInfo * notif_data = reinterpret_cast < SceNpMatching2RoomUpdateInfo * > ( allocate_req_result ( event_key , sizeof ( SceNpMatching2RoomUpdateInfo ) ) ) ;
RoomUpdateInfo_to_SceNpMatching2RoomUpdateInfo ( update_info , notif_data ) ;
2020-09-23 20:12:42 +02:00
rpcn_log . notice ( " Received notification that room(%d) was destroyed " , room_id ) ;
2021-03-02 12:59:19 +01:00
auto & sigh = g_fxo - > get < named_thread < signaling_handler > > ( ) ;
sigh . disconnect_sig2_users ( room_id ) ;
2020-09-07 23:50:17 +02:00
2021-03-02 12:59:19 +01:00
sysutil_register_cb ( [ room_event_cb = this - > room_event_cb , room_event_cb_ctx = this - > room_event_cb_ctx , room_id , event_key , room_event_cb_arg = this - > room_event_cb_arg ] ( ppu_thread & cb_ppu ) - > s32
{
2020-08-27 21:47:04 +02:00
room_event_cb ( cb_ppu , room_event_cb_ctx , room_id , SCE_NP_MATCHING2_ROOM_EVENT_RoomDestroyed , event_key , 0 , sizeof ( SceNpMatching2RoomUpdateInfo ) , room_event_cb_arg ) ;
return 0 ;
} ) ;
}
2020-09-07 23:50:17 +02:00
void np_handler : : notif_p2p_connect ( std : : vector < u8 > & data )
2020-08-27 21:47:04 +02:00
{
if ( data . size ( ) ! = 16 )
{
2020-09-07 23:50:17 +02:00
rpcn_log . error ( " Notification data for SignalP2PConnect != 14 " ) ;
2020-08-27 21:47:04 +02:00
return ;
}
const u64 room_id = reinterpret_cast < le_t < u64 > & > ( data [ 0 ] ) ;
const u16 member_id = reinterpret_cast < le_t < u16 > & > ( data [ 8 ] ) ;
2020-09-07 23:50:17 +02:00
const u16 port_p2p = reinterpret_cast < be_t < u16 > & > ( data [ 10 ] ) ;
2020-08-27 21:47:04 +02:00
const u32 addr_p2p = reinterpret_cast < le_t < u32 > & > ( data [ 12 ] ) ;
2020-09-23 20:12:42 +02:00
rpcn_log . notice ( " Received notification to connect to member(%d) of room(%d): %s:%d " , member_id , room_id , ip_to_string ( addr_p2p ) , port_p2p ) ;
2020-09-07 23:50:17 +02:00
// Attempt Signaling
2021-03-02 12:59:19 +01:00
auto & sigh = g_fxo - > get < named_thread < signaling_handler > > ( ) ;
sigh . set_sig2_infos ( room_id , member_id , SCE_NP_SIGNALING_CONN_STATUS_PENDING , addr_p2p , port_p2p ) ;
sigh . start_sig2 ( room_id , member_id ) ;
2020-08-27 21:47:04 +02:00
}
void np_handler : : notif_room_message_received ( std : : vector < u8 > & data )
{
vec_stream noti ( data ) ;
u64 room_id = noti . get < u64 > ( ) ;
u16 member_id = noti . get < u16 > ( ) ;
auto message_info_raw = noti . get_rawdata ( ) ;
if ( noti . is_error ( ) )
{
rpcn_log . error ( " Received faulty RoomMessageReceived notification " ) ;
return ;
}
u32 event_key = get_event_key ( ) ;
auto message_info = flatbuffers : : GetRoot < RoomMessageInfo > ( message_info_raw . data ( ) ) ;
SceNpMatching2RoomMessageInfo * notif_data = reinterpret_cast < SceNpMatching2RoomMessageInfo * > ( allocate_req_result ( event_key , sizeof ( SceNpMatching2RoomMessageInfo ) ) ) ;
RoomMessageInfo_to_SceNpMatching2RoomMessageInfo ( message_info , notif_data ) ;
2020-09-23 20:12:42 +02:00
rpcn_log . notice ( " Received notification of a room message from member(%d) in room(%d) " , member_id , room_id ) ;
2020-08-27 21:47:04 +02:00
if ( room_msg_cb )
{
sysutil_register_cb ( [ room_msg_cb = this - > room_msg_cb , room_msg_cb_ctx = this - > room_msg_cb_ctx , room_id , member_id , event_key , room_msg_cb_arg = this - > room_msg_cb_arg ] ( ppu_thread & cb_ppu ) - > s32
{
room_msg_cb ( cb_ppu , room_msg_cb_ctx , room_id , member_id , SCE_NP_MATCHING2_ROOM_MSG_EVENT_Message , event_key , 0 , sizeof ( SceNpMatching2RoomUpdateInfo ) , room_msg_cb_arg ) ;
return 0 ;
} ) ;
}
}
2020-03-04 14:55:35 +01:00
void np_handler : : add_dns_spy ( u32 sock )
{
dns_spylist . emplace ( std : : make_pair ( sock , std : : queue < std : : vector < u8 > > ( ) ) ) ;
}
void np_handler : : remove_dns_spy ( u32 sock )
{
dns_spylist . erase ( sock ) ;
}
bool np_handler : : is_dns ( u32 sock ) const
{
return dns_spylist . count ( sock ) ! = 0 ;
}
bool np_handler : : is_dns_queue ( u32 sock ) const
{
return ! dns_spylist . at ( sock ) . empty ( ) ;
}
std : : vector < u8 > np_handler : : get_dns_packet ( u32 sock )
{
auto ret_vec = std : : move ( dns_spylist . at ( sock ) . front ( ) ) ;
dns_spylist . at ( sock ) . pop ( ) ;
return ret_vec ;
}
s32 np_handler : : analyze_dns_packet ( s32 s , const u8 * buf , u32 len )
{
if ( sys_net . enabled = = logs : : level : : trace )
{
std : : string datrace ;
const char hex [ 16 ] = { ' 0 ' , ' 1 ' , ' 2 ' , ' 3 ' , ' 4 ' , ' 5 ' , ' 6 ' , ' 7 ' , ' 8 ' , ' 9 ' , ' A ' , ' B ' , ' C ' , ' D ' , ' E ' , ' F ' } ;
for ( u32 index = 0 ; index < len ; index + + )
{
if ( ( index % 16 ) = = 0 )
datrace + = ' \n ' ;
datrace + = hex [ ( buf [ index ] > > 4 ) & 15 ] ;
datrace + = hex [ ( buf [ index ] ) & 15 ] ;
datrace + = ' ' ;
}
sys_net . trace ( " DNS REQUEST: %s " , datrace ) ;
}
struct dns_header
{
u16 id ; // identification number
u8 rd : 1 ; // recursion desired
u8 tc : 1 ; // truncated message
u8 aa : 1 ; // authoritive answer
u8 opcode : 4 ; // purpose of message
u8 qr : 1 ; // query/response flag
u8 rcode : 4 ; // response code
u8 cd : 1 ; // checking disabled
u8 ad : 1 ; // authenticated data
u8 z : 1 ; // its z! reserved
u8 ra : 1 ; // recursion available
be_t < u16 > q_count ; // number of question entries
be_t < u16 > ans_count ; // number of answer entries
be_t < u16 > auth_count ; // number of authority entries
be_t < u16 > add_count ; // number of resource entries
} ;
if ( len < sizeof ( dns_header ) )
return - 1 ;
const dns_header * dhead = reinterpret_cast < const dns_header * > ( buf ) ;
// We are only looking for queries not truncated(todo?), only handle one dns query at a time(todo?)
if ( dhead - > qr ! = 0 | | dhead - > tc ! = 0 | | dhead - > q_count ! = 1 | | dhead - > ans_count ! = 0 | | dhead - > auth_count ! = 0 | | dhead - > add_count ! = 0 )
return - 1 ;
// Get the actual address
u8 count = 0 ;
std : : string host { } ;
for ( u32 i = sizeof ( dns_header ) ; ( i < len ) & & buf [ i ] ! = 0 ; i + + )
{
if ( count = = 0 )
{
count = buf [ i ] ;
if ( i ! = sizeof ( dns_header ) )
{
host + = ' . ' ;
}
}
else
{
host + = static_cast < char > ( buf [ i ] ) ;
count - - ;
}
}
sys_net . warning ( " DNS query for %s " , host ) ;
if ( switch_map . count ( host ) )
{
// design fake packet
std : : vector < u8 > fake ( len ) ;
memcpy ( fake . data ( ) , buf , len ) ;
dns_header * fake_header = reinterpret_cast < dns_header * > ( fake . data ( ) ) ;
fake_header - > qr = 1 ;
fake_header - > ra = 1 ;
fake_header - > ans_count = 1 ;
fake . insert ( fake . end ( ) , { 0xC0 , 0x0C } ) ; // Ref to name in header
fake . insert ( fake . end ( ) , { 0x00 , 0x01 } ) ; // IPv4
fake . insert ( fake . end ( ) , { 0x00 , 0x01 } ) ; // Class?
fake . insert ( fake . end ( ) , { 0x00 , 0x00 , 0x00 , 0x3B } ) ; // TTL
fake . insert ( fake . end ( ) , { 0x00 , 0x04 } ) ; // Size of data
u32 ip = switch_map [ host ] ;
u8 * ptr_ip = reinterpret_cast < u8 * > ( & ip ) ;
fake . insert ( fake . end ( ) , ptr_ip , ptr_ip + 4 ) ; // IP
sys_net . warning ( " Solving %s to %d.%d.%d.%d " , host , ptr_ip [ 0 ] , ptr_ip [ 1 ] , ptr_ip [ 2 ] , ptr_ip [ 3 ] ) ;
dns_spylist [ s ] . push ( std : : move ( fake ) ) ;
return len ;
}
return - 1 ;
}
2020-08-27 21:47:04 +02:00
bool np_handler : : error_and_disconnect ( const std : : string & error_msg )
{
rpcn_log . error ( " %s " , error_msg ) ;
rpcn . disconnect ( ) ;
return false ;
}
u32 np_handler : : generate_callback_info ( SceNpMatching2ContextId ctx_id , vm : : cptr < SceNpMatching2RequestOptParam > optParam )
{
callback_info ret ;
const auto ctx = get_match2_context ( ctx_id ) ;
2020-12-09 16:04:52 +01:00
ensure ( ctx ) ;
2020-08-27 21:47:04 +02:00
const u32 req_id = get_req_id ( optParam ? optParam - > appReqId : ctx - > default_match2_optparam . appReqId ) ;
ret . ctx_id = ctx_id ;
ret . cb = optParam ? optParam - > cbFunc : ctx - > default_match2_optparam . cbFunc ;
ret . cb_arg = optParam ? optParam - > cbFuncArg : ctx - > default_match2_optparam . cbFuncArg ;
nph_log . warning ( " Callback used is 0x%x " , ret . cb ) ;
pending_requests [ req_id ] = std : : move ( ret ) ;
return req_id ;
}
2020-12-18 08:39:54 +01:00
u8 * np_handler : : allocate_req_result ( u32 event_key , usz size )
2020-08-27 21:47:04 +02:00
{
std : : lock_guard lock ( mutex_req_results ) ;
match2_req_results [ event_key ] = std : : vector < u8 > ( size , 0 ) ;
return match2_req_results [ event_key ] . data ( ) ;
}
2021-03-05 20:05:37 +01:00
u32 np_handler : : add_players_to_history ( vm : : cptr < SceNpId > /*npids*/ , u32 /*count*/ )
2020-08-27 21:47:04 +02:00
{
const u32 req_id = get_req_id ( 0 ) ;
// if (basic_handler)
// {
2021-03-02 12:59:19 +01:00
// sysutil_register_cb([basic_handler = this->basic_handler, req_id, basic_handler_arg = this->basic_handler_arg](ppu_thread& cb_ppu) -> s32
// {
2020-08-27 21:47:04 +02:00
// basic_handler(cb_ppu, SCE_NP_BASIC_EVENT_ADD_PLAYERS_HISTORY_RESULT, 0, req_id, basic_handler_arg);
// return 0;
// });
// }
return req_id ;
2020-03-04 14:55:35 +01:00
}