rpcs3/rpcs3/Emu/NP/np_handler.h

526 lines
27 KiB
C++

#pragma once
#include <queue>
#include <map>
#include <unordered_map>
#include "Emu/Memory/vm_ptr.h"
#include "Emu/Cell/Modules/sceNp.h"
#include "Emu/Cell/Modules/sceNp2.h"
#include "Emu/Cell/Modules/cellSysutil.h"
#include "Emu/NP/rpcn_client.h"
#include "Emu/NP/np_allocator.h"
#include "Emu/NP/np_cache.h"
#include "Emu/NP/np_gui_cache.h"
#include "Emu/NP/np_event_data.h"
#include "Emu/NP/np_contexts.h"
#include "Emu/NP/upnp_handler.h"
namespace np
{
constexpr usz MAX_SceNpMatchingAttr_list_SIZE = ((SCE_NP_MATCHING_ATTR_ID_MAX * 2) * sizeof(SceNpMatchingAttr))
+ (SCE_NP_MATCHING_ATTR_BIN_BIG_SIZE_ID_MAX * SCE_NP_MATCHING_ATTR_BIN_MAX_SIZE_BIG) +
+ ((SCE_NP_MATCHING_ATTR_ID_MAX - SCE_NP_MATCHING_ATTR_BIN_BIG_SIZE_ID_MAX) * SCE_NP_MATCHING_ATTR_BIN_MAX_SIZE_SMALL);
constexpr usz MAX_MEMBERS_PER_ROOM = 64;
constexpr usz MAX_ROOMS_PER_GET_ROOM_LIST = 20;
constexpr usz MAX_SceNpMatchingRoomStatus_SIZE = sizeof(SceNpMatchingRoomStatus) + (MAX_MEMBERS_PER_ROOM * sizeof(SceNpMatchingRoomMember)) + sizeof(SceNpId);
constexpr usz MAX_SceNpMatchingJoinedRoomInfo_SIZE = sizeof(SceNpMatchingJoinedRoomInfo) + (MAX_MEMBERS_PER_ROOM * sizeof(SceNpMatchingRoomMember)) + sizeof(SceNpId);
constexpr usz MAX_SceNpMatchingRoomList_SIZE = sizeof(SceNpMatchingRoomList) + MAX_ROOMS_PER_GET_ROOM_LIST * (sizeof(SceNpMatchingRoom) + MAX_SceNpMatchingAttr_list_SIZE);
constexpr usz MAX_SceNpMatchingRoom_SIZE = sizeof(SceNpMatchingRoom) + MAX_SceNpMatchingAttr_list_SIZE;
constexpr usz MAX_SceNpMatchingSearchJoinRoomInfo_SIZE = sizeof(SceNpMatchingSearchJoinRoomInfo) + MAX_SceNpMatchingAttr_list_SIZE;
enum class REQUEST_ID_HIGH : u16
{
MISC = 0x3333,
SCORE = 0x3334,
TUS = 0x3335,
GUI = 0x3336,
};
struct ticket_data
{
u16 id{}, len{};
struct
{
u32 data_u32{};
u64 data_u64{};
std::vector<u8> data_vec;
std::vector<ticket_data> data_nodes;
} data;
};
struct player_history
{
u64 timestamp{};
std::set<std::string> communication_ids;
std::string description;
};
class ticket
{
public:
ticket() = default;
ticket(std::vector<u8>&& raw_data);
std::size_t size() const;
const u8* data() const;
bool empty() const;
bool get_value(s32 param_id, vm::ptr<SceNpTicketParam> param) const;
private:
std::optional<ticket_data> parse_node(std::size_t index) const;
void parse();
private:
static constexpr std::size_t MIN_TICKET_DATA_SIZE = 4;
std::vector<u8> raw_data;
bool parse_success = false;
u32 version{};
std::vector<ticket_data> nodes;
};
struct basic_event
{
s32 event = 0;
SceNpUserInfo from{};
std::vector<u8> data;
};
class np_handler
{
public:
SAVESTATE_INIT_POS(5);
np_handler();
~np_handler();
np_handler(utils::serial& ar);
void save(utils::serial& ar);
void init_np_handler_dependencies();
const std::array<u8, 6>& get_ether_addr() const;
const std::string& get_hostname() const;
u32 get_local_ip_addr() const;
u32 get_public_ip_addr() const;
u32 get_dns_ip() const;
u32 get_bind_ip() const;
s32 get_psn_status() const;
s32 get_net_status() const;
s32 get_upnp_status() const;
const SceNpId& get_npid() const;
const SceNpOnlineId& get_online_id() const;
const SceNpOnlineName& get_online_name() const;
const SceNpAvatarUrl& get_avatar_url() const;
// handles async messages from server(only needed for RPCN)
void operator()();
void init_NP(u32 poolsize, vm::ptr<void> poolptr);
void terminate_NP();
atomic_t<bool> is_netctl_init = false;
atomic_t<bool> is_NP_init = false;
atomic_t<bool> is_NP_Lookup_init = false;
atomic_t<bool> is_NP_Score_init = false;
atomic_t<bool> is_NP2_init = false;
atomic_t<bool> is_NP2_Match2_init = false;
atomic_t<bool> is_NP_Auth_init = false;
atomic_t<bool> is_NP_TUS_init = false; // TODO: savestate
atomic_t<bool> is_NP_Com2_init = false; // TODO: savestate
// NP Handlers/Callbacks
// Seems to be global
vm::ptr<SceNpManagerCallback> manager_cb{}; // Connection status and tickets
vm::ptr<void> manager_cb_arg{};
atomic_t<bool> basic_handler_registered = false;
void register_basic_handler(vm::cptr<SceNpCommunicationId> context, vm::ptr<SceNpBasicEventHandler> handler, vm::ptr<void> arg, bool context_sensitive);
SceNpCommunicationId get_basic_handler_context();
void queue_basic_event(basic_event to_queue);
bool send_basic_event(s32 event, s32 retCode, u32 reqId);
error_code get_basic_event(vm::ptr<s32> event, vm::ptr<SceNpUserInfo> from, vm::ptr<u8> data, vm::ptr<u32> size);
// Messages-related functions
std::optional<shared_ptr<std::pair<std::string, message_data>>> get_message(u64 id);
void set_message_selected(SceNpBasicAttachmentDataId id, u64 msg_id);
std::optional<shared_ptr<std::pair<std::string, message_data>>> get_message_selected(SceNpBasicAttachmentDataId id);
void clear_message_selected(SceNpBasicAttachmentDataId id);
void send_message(const message_data& msg_data, const std::set<std::string>& npids);
// Those should probably be under match2 ctx
vm::ptr<SceNpMatching2RoomEventCallback> room_event_cb{}; // Room events
u16 room_event_cb_ctx = 0;
vm::ptr<void> room_event_cb_arg{};
vm::ptr<SceNpMatching2RoomMessageCallback> room_msg_cb{};
u16 room_msg_cb_ctx = 0;
vm::ptr<void> room_msg_cb_arg{};
// Synchronous requests
std::vector<SceNpMatching2ServerId> get_match2_server_list(SceNpMatching2ContextId);
u64 get_network_time();
// Asynchronous requests
u32 get_server_status(SceNpMatching2ContextId ctx_id, vm::cptr<SceNpMatching2RequestOptParam> optParam, u16 server_id);
u32 create_server_context(SceNpMatching2ContextId ctx_id, vm::cptr<SceNpMatching2RequestOptParam> optParam, u16 server_id);
u32 delete_server_context(SceNpMatching2ContextId ctx_id, vm::cptr<SceNpMatching2RequestOptParam> optParam, u16 server_id);
u32 get_world_list(SceNpMatching2ContextId ctx_id, vm::cptr<SceNpMatching2RequestOptParam> optParam, u16 server_id);
u32 create_join_room(SceNpMatching2ContextId ctx_id, vm::cptr<SceNpMatching2RequestOptParam> optParam, const SceNpMatching2CreateJoinRoomRequest* req);
u32 join_room(SceNpMatching2ContextId ctx_id, vm::cptr<SceNpMatching2RequestOptParam> optParam, const SceNpMatching2JoinRoomRequest* req);
u32 leave_room(SceNpMatching2ContextId ctx_id, vm::cptr<SceNpMatching2RequestOptParam> optParam, const SceNpMatching2LeaveRoomRequest* req);
u32 search_room(SceNpMatching2ContextId ctx_id, vm::cptr<SceNpMatching2RequestOptParam> optParam, const SceNpMatching2SearchRoomRequest* req);
u32 get_roomdata_external_list(SceNpMatching2ContextId ctx_id, vm::cptr<SceNpMatching2RequestOptParam> optParam, const SceNpMatching2GetRoomDataExternalListRequest* req);
u32 set_roomdata_external(SceNpMatching2ContextId ctx_id, vm::cptr<SceNpMatching2RequestOptParam> optParam, const SceNpMatching2SetRoomDataExternalRequest* req);
u32 get_roomdata_internal(SceNpMatching2ContextId ctx_id, vm::cptr<SceNpMatching2RequestOptParam> optParam, const SceNpMatching2GetRoomDataInternalRequest* req);
u32 set_roomdata_internal(SceNpMatching2ContextId ctx_id, vm::cptr<SceNpMatching2RequestOptParam> optParam, const SceNpMatching2SetRoomDataInternalRequest* req);
u32 get_roommemberdata_internal(SceNpMatching2ContextId ctx_id, vm::cptr<SceNpMatching2RequestOptParam> optParam, const SceNpMatching2GetRoomMemberDataInternalRequest* req);
u32 set_roommemberdata_internal(SceNpMatching2ContextId ctx_id, vm::cptr<SceNpMatching2RequestOptParam> optParam, const SceNpMatching2SetRoomMemberDataInternalRequest* req);
u32 set_userinfo(SceNpMatching2ContextId ctx_id, vm::cptr<SceNpMatching2RequestOptParam> optParam, const SceNpMatching2SetUserInfoRequest* req);
u32 get_ping_info(SceNpMatching2ContextId ctx_id, vm::cptr<SceNpMatching2RequestOptParam> optParam, const SceNpMatching2SignalingGetPingInfoRequest* req);
u32 send_room_message(SceNpMatching2ContextId ctx_id, vm::cptr<SceNpMatching2RequestOptParam> optParam, const SceNpMatching2SendRoomMessageRequest* req);
u32 get_lobby_info_list(SceNpMatching2ContextId ctx_id, vm::cptr<SceNpMatching2RequestOptParam> optParam, const SceNpMatching2GetLobbyInfoListRequest* req);
u32 get_match2_event(SceNpMatching2EventKey event_key, u32 dest_addr, u32 size);
// Old GUI Matching requests
error_code get_matching_result(u32 ctx_id, u32 req_id, vm::ptr<void> buf, vm::ptr<u32> size, vm::ptr<s32> event);
error_code get_result_gui(vm::ptr<void> buf, vm::ptr<u32> size, vm::ptr<s32> event);
error_code create_room_gui(u32 ctx_id, vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpMatchingAttr> attr, vm::ptr<SceNpMatchingGUIHandler> handler, vm::ptr<void> arg);
error_code join_room_gui(u32 ctx_id, vm::ptr<SceNpRoomId> roomid, vm::ptr<SceNpMatchingGUIHandler> handler, vm::ptr<void> arg);
error_code leave_room_gui(u32 ctx_id, vm::cptr<SceNpRoomId> roomid);
error_code get_room_list_gui(u32 ctx_id, vm::cptr<SceNpCommunicationId> communicationId, vm::ptr<SceNpMatchingReqRange> range, vm::ptr<SceNpMatchingSearchCondition> cond, vm::ptr<SceNpMatchingAttr> attr, vm::ptr<SceNpMatchingGUIHandler> handler, vm::ptr<void> arg, bool limit);
error_code set_room_search_flag_gui(u32 ctx_id, vm::ptr<SceNpLobbyId> lobby_id, vm::ptr<SceNpRoomId> room_id, s32 flag);
error_code get_room_search_flag_gui(u32 ctx_id, vm::ptr<SceNpLobbyId> lobby_id, vm::ptr<SceNpRoomId> room_id);
error_code set_room_info_gui(u32 ctx_id, vm::ptr<SceNpLobbyId> lobby_id, vm::ptr<SceNpRoomId> room_id, vm::ptr<SceNpMatchingAttr> attr);
error_code get_room_info_gui(u32 ctx_id, vm::ptr<SceNpLobbyId> lobby_id, vm::ptr<SceNpRoomId> room_id, vm::ptr<SceNpMatchingAttr> attr);
error_code quickmatch_gui(u32 ctx_id, vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpMatchingSearchCondition> cond, s32 available_num, s32 timeout, vm::ptr<SceNpMatchingGUIHandler> handler, vm::ptr<void> arg);
error_code searchjoin_gui(u32 ctx_id, vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpMatchingSearchCondition> cond, vm::cptr<SceNpMatchingAttr> attr, vm::ptr<SceNpMatchingGUIHandler> handler, vm::ptr<void> arg);
void set_current_gui_ctx_id(u32 id);
// Score requests
void transaction_async_handler(std::unique_lock<shared_mutex> lock, const shared_ptr<generic_async_transaction_context>& trans_ctx, u32 req_id, bool async);
void get_board_infos(shared_ptr<score_transaction_ctx>& trans_ctx, SceNpScoreBoardId boardId, vm::ptr<SceNpScoreBoardInfo> boardInfo, bool async);
void record_score(shared_ptr<score_transaction_ctx>& trans_ctx, SceNpScoreBoardId boardId, SceNpScoreValue score, vm::cptr<SceNpScoreComment> scoreComment, const u8* data, u32 data_size, vm::ptr<SceNpScoreRankNumber> tmpRank, bool async);
void record_score_data(shared_ptr<score_transaction_ctx>& trans_ctx, SceNpScoreBoardId boardId, SceNpScoreValue score, u32 totalSize, u32 sendSize, const u8* score_data, bool async);
void get_score_data(shared_ptr<score_transaction_ctx>& trans_ctx, SceNpScoreBoardId boardId, const SceNpId& npId, vm::ptr<u32> totalSize, u32 recvSize, vm::ptr<void> score_data, bool async);
void get_score_range(shared_ptr<score_transaction_ctx>& trans_ctx, SceNpScoreBoardId boardId, SceNpScoreRankNumber startSerialRank, vm::ptr<SceNpScoreRankData> rankArray, u32 rankArraySize, vm::ptr<SceNpScoreComment> commentArray, u32 commentArraySize, vm::ptr<void> infoArray, u32 infoArraySize, u32 arrayNum, vm::ptr<CellRtcTick> lastSortDate, vm::ptr<SceNpScoreRankNumber> totalRecord, bool async, bool deprecated);
void get_score_npid(shared_ptr<score_transaction_ctx>& trans_ctx, SceNpScoreBoardId boardId, const std::vector<std::pair<SceNpId, s32>>& npid_vec, vm::ptr<SceNpScorePlayerRankData> rankArray, u32 rankArraySize, vm::ptr<SceNpScoreComment> commentArray, u32 commentArraySize, vm::ptr<void> infoArray, u32 infoArraySize, u32 arrayNum, vm::ptr<CellRtcTick> lastSortDate, vm::ptr<SceNpScoreRankNumber> totalRecord, bool async, bool deprecated);
void get_score_friend(shared_ptr<score_transaction_ctx>& trans_ctx, SceNpScoreBoardId boardId, bool include_self, vm::ptr<SceNpScoreRankData> rankArray, u32 rankArraySize, vm::ptr<SceNpScoreComment> commentArray, u32 commentArraySize, vm::ptr<void> infoArray, u32 infoArraySize, u32 arrayNum, vm::ptr<CellRtcTick> lastSortDate, vm::ptr<SceNpScoreRankNumber> totalRecord, bool async, bool deprecated);
// TUS requests
void tus_set_multislot_variable(shared_ptr<tus_transaction_ctx>& trans_ctx, const SceNpOnlineId& targetNpId, vm::cptr<SceNpTusSlotId> slotIdArray, vm::cptr<s64> variableArray, s32 arrayNum, bool vuser, bool async);
void tus_get_multislot_variable(shared_ptr<tus_transaction_ctx>& trans_ctx, const SceNpOnlineId& targetNpId, vm::cptr<SceNpTusSlotId> slotIdArray, vm::ptr<SceNpTusVariable> variableArray, s32 arrayNum, bool vuser, bool async);
void tus_get_multiuser_variable(shared_ptr<tus_transaction_ctx>& trans_ctx, std::vector<SceNpOnlineId> targetNpIdArray, SceNpTusSlotId slotId, vm::ptr<SceNpTusVariable> variableArray, s32 arrayNum, bool vuser, bool async);
void tus_get_friends_variable(shared_ptr<tus_transaction_ctx>& trans_ctx, SceNpTusSlotId slotId, s32 includeSelf, s32 sortType, vm::ptr<SceNpTusVariable> variableArray,s32 arrayNum, bool async);
void tus_add_and_get_variable(shared_ptr<tus_transaction_ctx>& trans_ctx, const SceNpOnlineId& targetNpId, SceNpTusSlotId slotId, s64 inVariable, vm::ptr<SceNpTusVariable> outVariable, vm::ptr<SceNpTusAddAndGetVariableOptParam> option, bool vuser, bool async);
void tus_try_and_set_variable(shared_ptr<tus_transaction_ctx>& trans_ctx, const SceNpOnlineId& targetNpId, SceNpTusSlotId slotId, s32 opeType, s64 variable, vm::ptr<SceNpTusVariable> resultVariable, vm::ptr<SceNpTusTryAndSetVariableOptParam> option, bool vuser, bool async);
void tus_delete_multislot_variable(shared_ptr<tus_transaction_ctx>& trans_ctx, const SceNpOnlineId& targetNpId, vm::cptr<SceNpTusSlotId> slotIdArray, s32 arrayNum, bool vuser, bool async);
void tus_set_data(shared_ptr<tus_transaction_ctx>& trans_ctx, const SceNpOnlineId& targetNpId, SceNpTusSlotId slotId, u32 totalSize, u32 sendSize, vm::cptr<void> data, vm::cptr<SceNpTusDataInfo> info, vm::ptr<SceNpTusSetDataOptParam> option, bool vuser, bool async);
void tus_get_data(shared_ptr<tus_transaction_ctx>& trans_ctx, const SceNpOnlineId& targetNpId, SceNpTusSlotId slotId, vm::ptr<SceNpTusDataStatus> dataStatus, vm::ptr<void> data, u32 recvSize, bool vuser, bool async);
void tus_get_multislot_data_status(shared_ptr<tus_transaction_ctx>& trans_ctx, const SceNpOnlineId& targetNpId, vm::cptr<SceNpTusSlotId> slotIdArray, vm::ptr<SceNpTusDataStatus> statusArray, s32 arrayNum, bool vuser, bool async);
void tus_get_multiuser_data_status(shared_ptr<tus_transaction_ctx>& trans_ctx, std::vector<SceNpOnlineId> targetNpIdArray, SceNpTusSlotId slotId, vm::ptr<SceNpTusDataStatus> statusArray, s32 arrayNum, bool vuser, bool async);
void tus_get_friends_data_status(shared_ptr<tus_transaction_ctx>& trans_ctx, SceNpTusSlotId slotId, s32 includeSelf, s32 sortType, vm::ptr<SceNpTusDataStatus> statusArray, s32 arrayNum, bool async);
void tus_delete_multislot_data(shared_ptr<tus_transaction_ctx>& trans_ctx, const SceNpOnlineId& targetNpId, vm::cptr<SceNpTusSlotId> slotIdArray, s32 arrayNum, bool vuser, bool async);
// Local functions
std::pair<error_code, std::optional<SceNpId>> local_get_npid(u64 room_id, u16 member_id);
std::pair<error_code, std::optional<SceNpMatching2RoomSlotInfo>> local_get_room_slots(SceNpMatching2RoomId room_id);
std::pair<error_code, std::optional<SceNpMatching2SessionPassword>> local_get_room_password(SceNpMatching2RoomId room_id);
std::pair<error_code, std::vector<SceNpMatching2RoomMemberId>> local_get_room_memberids(SceNpMatching2RoomId room_id, s32 sort_method);
error_code local_get_room_member_data(SceNpMatching2RoomId room_id, SceNpMatching2RoomMemberId member_id, const std::vector<SceNpMatching2AttributeId>& binattrs_list, SceNpMatching2RoomMemberDataInternal* ptr_member, u32 addr_data, u32 size_data, u32 ctx_id);
// Local GUI functions
error_code get_room_member_list_local_gui(u32 ctx_id, vm::ptr<SceNpRoomId> room_id, vm::ptr<u32> buflen, vm::ptr<void> buf);
// Friend stuff
u32 get_num_friends();
u32 get_num_blocks();
std::pair<error_code, std::optional<SceNpId>> get_friend_by_index(u32 index);
void set_presence(std::optional<std::string> status, std::optional<std::vector<u8>> data);
template <typename T>
error_code get_friend_presence_by_index(u32 index, SceNpUserInfo* user, T* pres);
template <typename T>
error_code get_friend_presence_by_npid(const SceNpId& npid, T* pres);
// Misc stuff
void req_ticket(u32 version, const SceNpId* npid, const char* service_id, const u8* cookie, u32 cookie_size, const char* entitlement_id, u32 consumed_count);
const ticket& get_ticket() const;
void add_player_to_history(const SceNpId* npid, const char* description);
u32 add_players_to_history(const SceNpId* npids, const char* description, u32 count);
u32 get_players_history_count(u32 options);
bool get_player_history_entry(u32 options, u32 index, SceNpId* npid);
bool abort_request(u32 req_id);
// For signaling
void req_sign_infos(const std::string& npid, u32 conn_id);
// For UPNP
void upnp_add_port_mapping(u16 internal_port, std::string_view protocol);
void upnp_remove_port_mapping(u16 internal_port, std::string_view protocol);
// For custom menu
struct custom_menu_action
{
s32 id = 0;
u32 mask = SCE_NP_CUSTOM_MENU_ACTION_MASK_ME;
std::string name;
};
shared_mutex mutex_custom_menu;
bool custom_menu_registered = false;
vm::ptr<SceNpCustomMenuEventHandler> custom_menu_handler{};
vm::ptr<void> custom_menu_user_arg{};
std::vector<custom_menu_action> custom_menu_actions;
SceNpCustomMenuIndexArray custom_menu_activation{};
std::vector<SceNpCustomMenuActionExceptions> custom_menu_exception_list{};
// Mutex for NP status change
shared_mutex mutex_status;
static constexpr std::string_view thread_name = "NP Handler Thread";
private:
// Various generic helpers
bool discover_ip_address();
bool discover_ether_address();
bool error_and_disconnect(const std::string& error_msg);
// Notification handlers
void notif_user_joined_room(vec_stream& noti);
void notif_user_left_room(vec_stream& noti);
void notif_room_destroyed(vec_stream& noti);
void notif_updated_room_data_internal(vec_stream& noti);
void notif_updated_room_member_data_internal(vec_stream& noti);
void notif_signaling_helper(vec_stream& noti);
void notif_room_message_received(vec_stream& noti);
void generic_gui_notification_handler(vec_stream& noti, std::string_view name, s32 notification_type);
void notif_member_joined_room_gui(vec_stream& noti);
void notif_member_left_room_gui(vec_stream& noti);
void notif_room_disappeared_gui(vec_stream& noti);
void notif_room_owner_changed_gui(vec_stream& noti);
void notif_user_kicked_gui(vec_stream& noti);
void notif_quickmatch_complete_gui(vec_stream& noti);
// Reply handlers
void reply_get_world_list(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
void reply_create_join_room(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
void reply_join_room(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
void reply_leave_room(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
void reply_search_room(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
void reply_get_roomdata_external_list(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
void reply_set_roomdata_external(u32 req_id, rpcn::ErrorType error);
void reply_get_roomdata_internal(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
void reply_set_roomdata_internal(u32 req_id, rpcn::ErrorType error);
void reply_set_roommemberdata_internal(u32 req_id, rpcn::ErrorType error);
void reply_get_roommemberdata_internal(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
void reply_set_userinfo(u32 req_id, rpcn::ErrorType error);
void reply_get_ping_info(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
void reply_send_room_message(u32 req_id, rpcn::ErrorType error);
void reply_req_sign_infos(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
void reply_req_ticket(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
void reply_get_board_infos(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
void reply_record_score(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
void reply_record_score_data(u32 req_id, rpcn::ErrorType error);
void reply_get_score_data(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
void reply_get_score_range(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
void reply_get_score_friends(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
void reply_get_score_npid(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
void reply_tus_set_multislot_variable(u32 req_id, rpcn::ErrorType error);
void reply_tus_get_multislot_variable(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
void reply_tus_get_multiuser_variable(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
void reply_tus_get_friends_variable(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
void reply_tus_add_and_get_variable(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
void reply_tus_try_and_set_variable(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
void reply_tus_delete_multislot_variable(u32 req_id, rpcn::ErrorType error);
void reply_tus_set_data(u32 req_id, rpcn::ErrorType error);
void reply_tus_get_data(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
void reply_tus_get_multislot_data_status(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
void reply_tus_get_multiuser_data_status(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
void reply_tus_get_friends_data_status(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
void reply_tus_delete_multislot_data(u32 req_id, rpcn::ErrorType error);
void reply_create_room_gui(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
void reply_join_room_gui(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
void reply_leave_room_gui(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
void reply_get_room_list_gui(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
void reply_set_room_search_flag_gui(u32 req_id, rpcn::ErrorType error);
void reply_get_room_search_flag_gui(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
void reply_set_room_info_gui(u32 req_id, rpcn::ErrorType error);
void reply_get_room_info_gui(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
void reply_quickmatch_gui(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
void reply_searchjoin_gui(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
// Helper functions
std::pair<bool, bool> get_match2_context_options(u32 ctx_id);
void handle_GetScoreResponse(u32 req_id, rpcn::ErrorType error, vec_stream& reply, bool simple_result = false);
void handle_tus_no_data(u32 req_id, rpcn::ErrorType error);
void handle_TusVarResponse(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
void handle_TusVariable(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
void handle_TusDataStatusResponse(u32 req_id, rpcn::ErrorType error, vec_stream& reply);
struct callback_info
{
SceNpMatching2ContextId ctx_id;
vm::ptr<SceNpMatching2RequestCallback> cb;
vm::ptr<void> cb_arg;
SceNpMatching2Event event_type;
void queue_callback(u32 req_id, u32 event_key, s32 error_code, u32 data_size) const;
};
u32 generate_callback_info(SceNpMatching2ContextId ctx_id, vm::cptr<SceNpMatching2RequestOptParam> optParam, SceNpMatching2Event event_type);
std::optional<callback_info> take_pending_request(u32 req_id);
private:
shared_mutex mutex_pending_requests;
std::unordered_map<u32, callback_info> pending_requests;
shared_mutex mutex_pending_sign_infos_requests;
std::unordered_map<u32, u32> pending_sign_infos_requests;
shared_mutex mutex_queue_basic_events;
std::queue<basic_event> queue_basic_events;
bool m_inited_np_handler_dependencies = false;
// Basic event handler;
struct
{
shared_mutex mutex;
SceNpCommunicationId context{};
vm::ptr<SceNpBasicEventHandler> handler_func;
vm::ptr<void> handler_arg;
bool context_sensitive = false;
} basic_handler;
bool is_connected = false;
bool is_psn_active = false;
ticket current_ticket;
// IP & DNS info
std::string hostname = "localhost";
std::array<u8, 6> ether_address{};
be_t<u32> local_ip_addr{};
be_t<u32> public_ip_addr{};
be_t<u32> dns_ip = 0x08080808;
be_t<u32> bind_ip = 0x00000000;
// User infos
SceNpId npid{};
SceNpOnlineName online_name{};
SceNpAvatarUrl avatar_url{};
// Memory pool for sceNp/sceNp2
memory_allocator np_memory;
// Cache related
std::optional<SceNpMatching2SessionPassword> cached_cj_password;
cache_manager np_cache;
gui_cache_manager gui_cache;
// Messages related
std::optional<u64> selected_invite_id{};
std::optional<u64> selected_message_id{};
// Misc
s64 network_time_offset = 0;
// Requests(reqEventKey : data)
shared_mutex mutex_match2_req_results;
std::unordered_map<u32, event_data> match2_req_results;
atomic_t<u16> match2_low_reqid_cnt = 1;
atomic_t<u32> match2_event_cnt = 1;
u32 get_req_id(u16 app_req)
{
return ((app_req << 16) | match2_low_reqid_cnt.fetch_add(1));
}
u32 get_req_id(REQUEST_ID_HIGH int_req)
{
return ((static_cast<u16>(int_req) << 16) | match2_low_reqid_cnt.fetch_add(1));
}
u32 get_event_key()
{
return match2_event_cnt.fetch_add(1);
}
event_data& allocate_req_result(u32 event_key, u32 max_size, u32 initial_size);
// GUI result
struct
{
shared_mutex mutex;
s32 event = 0;
event_data data;
} gui_result;
void set_gui_result(s32 event, event_data data);
// GUI notifications
struct gui_notification
{
s32 event = 0;
event_data edata;
};
struct
{
shared_mutex mutex;
std::map<std::pair<u32, u32>, gui_notification> list; // (ctx_id, req_id), notif
u32 counter_req_id = 1;
u32 current_gui_ctx_id = 0;
} gui_notifications;
// Async transaction threads
shared_mutex mutex_async_transactions;
std::unordered_map<u32, shared_ptr<generic_async_transaction_context>> async_transactions; // (req_id, transaction_ctx)
// RPCN
shared_mutex mutex_rpcn;
std::shared_ptr<rpcn::rpcn_client> rpcn;
std::shared_ptr<rpcn::rpcn_client> get_rpcn();
// UPNP
upnp_handler upnp;
// Presence
struct
{
SceNpCommunicationId pr_com_id;
std::string pr_title;
std::string pr_status;
std::string pr_comment;
std::vector<u8> pr_data;
atomic_t<bool> advertised = false;
} presence_self;
player_history& get_player_and_set_timestamp(const SceNpId& npid, u64 timestamp);
void save_players_history();
shared_mutex mutex_history;
std::map<std::string, player_history> players_history; // npid / history
struct
{
shared_mutex mutex;
std::map<u32, u32> list; // req_id / ctx_id
} gui_requests;
void add_gui_request(u32 req_id, u32 ctx_id);
void remove_gui_request(u32 req_id);
u32 take_gui_request(u32 req_id);
shared_ptr<matching_ctx> take_pending_gui_request(u32 req_id);
shared_mutex mutex_quickmatching;
std::map<SceNpRoomId, u32> pending_quickmatching;
};
} // namespace np