mirror of
https://github.com/RPCSX/rpcsx.git
synced 2025-12-06 07:12:14 +01:00
Replaces `std::shared_pointer` with `stx::atomic_ptr` and `stx::shared_ptr`. Notes to programmers: * This pr kills the use of `dynamic_cast`, `std::dynamic_pointer_cast` and `std::weak_ptr` on IDM objects, possible replacement is to save the object ID on the base object, then use idm::check/get_unlocked to the destination type via the saved ID which may be null. Null pointer check is how you can tell type mismatch (as dynamic cast) or object destruction (as weak_ptr locking). * Double-inheritance on IDM objects should be used with care, `stx::shared_ptr` does not support constant-evaluated pointer offsetting to parent/child type. * `idm::check/get_unlocked` can now be used anywhere. Misc fixes: * Fixes some segfaults with RPCN with interaction with IDM. * Fix deadlocks in access violation handler due locking recursion. * Fixes race condition in process exit-spawn on memory containers read. * Fix bug that theoretically can prevent RPCS3 from booting - fix `id_manager::typeinfo` comparison to compare members instead of `memcmp` which can fail spuriously on padding bytes. * Ensure all IDM inherited types of base, either has `id_base` or `id_type` defined locally, this allows to make getters such as `idm::get_unlocked<lv2_socket, lv2_socket_raw>()` which were broken before. (requires save-states invalidation) * Removes broken operator[] overload of `stx::shared_ptr` and `stx::single_ptr` for non-array types.
538 lines
27 KiB
C++
538 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/generated/np2_structs_generated.h"
|
|
#include "Emu/NP/signaling_handler.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(std::vector<u8>& data);
|
|
void notif_user_left_room(std::vector<u8>& data);
|
|
void notif_room_destroyed(std::vector<u8>& data);
|
|
void notif_updated_room_data_internal(std::vector<u8>& data);
|
|
void notif_updated_room_member_data_internal(std::vector<u8>& data);
|
|
void notif_p2p_connect(std::vector<u8>& data);
|
|
void notif_signaling_info(std::vector<u8>& data);
|
|
void notif_room_message_received(std::vector<u8>& data);
|
|
|
|
void generic_gui_notification_handler(std::vector<u8>& data, std::string_view name, s32 notification_type);
|
|
|
|
void notif_member_joined_room_gui(std::vector<u8>& data);
|
|
void notif_member_left_room_gui(std::vector<u8>& data);
|
|
void notif_room_disappeared_gui(std::vector<u8>& data);
|
|
void notif_room_owner_changed_gui(std::vector<u8>& data);
|
|
void notif_user_kicked_gui(std::vector<u8>& data);
|
|
void notif_quickmatch_complete_gui(std::vector<u8>& data);
|
|
|
|
// Reply handlers
|
|
bool reply_get_world_list(u32 req_id, std::vector<u8>& reply_data);
|
|
bool reply_create_join_room(u32 req_id, std::vector<u8>& reply_data);
|
|
bool reply_join_room(u32 req_id, std::vector<u8>& reply_data);
|
|
bool reply_leave_room(u32 req_id, std::vector<u8>& reply_data);
|
|
bool reply_search_room(u32 req_id, std::vector<u8>& reply_data);
|
|
bool reply_get_roomdata_external_list(u32 req_id, std::vector<u8>& reply_data);
|
|
bool reply_set_roomdata_external(u32 req_id, std::vector<u8>& reply_data);
|
|
bool reply_get_roomdata_internal(u32 req_id, std::vector<u8>& reply_data);
|
|
bool reply_set_roomdata_internal(u32 req_id, std::vector<u8>& reply_data);
|
|
bool reply_set_roommemberdata_internal(u32 req_id, std::vector<u8>& reply_data);
|
|
bool reply_get_roommemberdata_internal(u32 req_id, std::vector<u8>& reply_data);
|
|
bool reply_set_userinfo(u32 req_id, std::vector<u8>& reply_data);
|
|
bool reply_get_ping_info(u32 req_id, std::vector<u8>& reply_data);
|
|
bool reply_send_room_message(u32 req_id, std::vector<u8>& reply_data);
|
|
bool reply_req_sign_infos(u32 req_id, std::vector<u8>& reply_data);
|
|
bool reply_req_ticket(u32 req_id, std::vector<u8>& reply_data);
|
|
bool reply_get_board_infos(u32 req_id, std::vector<u8>& reply_data);
|
|
bool reply_record_score(u32 req_id, std::vector<u8>& reply_data);
|
|
bool reply_record_score_data(u32 req_id, std::vector<u8>& reply_data);
|
|
bool reply_get_score_data(u32 req_id, std::vector<u8>& reply_data);
|
|
bool reply_get_score_range(u32 req_id, std::vector<u8>& reply_data);
|
|
bool reply_get_score_friends(u32 req_id, std::vector<u8>& reply_data);
|
|
bool reply_get_score_npid(u32 req_id, std::vector<u8>& reply_data);
|
|
bool reply_tus_set_multislot_variable(u32 req_id, std::vector<u8>& reply_data);
|
|
bool reply_tus_get_multislot_variable(u32 req_id, std::vector<u8>& reply_data);
|
|
bool reply_tus_get_multiuser_variable(u32 req_id, std::vector<u8>& reply_data);
|
|
bool reply_tus_get_friends_variable(u32 req_id, std::vector<u8>& reply_data);
|
|
bool reply_tus_add_and_get_variable(u32 req_id, std::vector<u8>& reply_data);
|
|
bool reply_tus_try_and_set_variable(u32 req_id, std::vector<u8>& reply_data);
|
|
bool reply_tus_delete_multislot_variable(u32 req_id, std::vector<u8>& reply_data);
|
|
bool reply_tus_set_data(u32 req_id, std::vector<u8>& reply_data);
|
|
bool reply_tus_get_data(u32 req_id, std::vector<u8>& reply_data);
|
|
bool reply_tus_get_multislot_data_status(u32 req_id, std::vector<u8>& reply_data);
|
|
bool reply_tus_get_multiuser_data_status(u32 req_id, std::vector<u8>& reply_data);
|
|
bool reply_tus_get_friends_data_status(u32 req_id, std::vector<u8>& reply_data);
|
|
bool reply_tus_delete_multislot_data(u32 req_id, std::vector<u8>& reply_data);
|
|
bool reply_create_room_gui(u32 req_id, std::vector<u8>& reply_data);
|
|
bool reply_join_room_gui(u32 req_id, std::vector<u8>& reply_data);
|
|
bool reply_leave_room_gui(u32 req_id, std::vector<u8>& reply_data);
|
|
bool reply_get_room_list_gui(u32 req_id, std::vector<u8>& reply_data);
|
|
bool reply_set_room_search_flag_gui(u32 req_id, std::vector<u8>& reply_data);
|
|
bool reply_get_room_search_flag_gui(u32 req_id, std::vector<u8>& reply_data);
|
|
bool reply_set_room_info_gui(u32 req_id, std::vector<u8>& reply_data);
|
|
bool reply_get_room_info_gui(u32 req_id, std::vector<u8>& reply_data);
|
|
bool reply_quickmatch_gui(u32 req_id, std::vector<u8>& reply_data);
|
|
bool reply_searchjoin_gui(u32 req_id, std::vector<u8>& reply_data);
|
|
|
|
// Helper functions
|
|
std::pair<bool, bool> get_match2_context_options(u32 ctx_id);
|
|
bool handle_GetScoreResponse(u32 req_id, std::vector<u8>& reply_data, bool simple_result = false);
|
|
bool handle_tus_no_data(u32 req_id, std::vector<u8>& reply_data);
|
|
bool handle_TusVarResponse(u32 req_id, std::vector<u8>& reply_data);
|
|
bool handle_TusVariable(u32 req_id, std::vector<u8>& reply_data);
|
|
bool handle_TusDataStatusResponse(u32 req_id, std::vector<u8>& reply_data);
|
|
|
|
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
|
|
{
|
|
if (cb)
|
|
{
|
|
sysutil_register_cb([=, ctx_id = this->ctx_id, event_type = this->event_type, cb = this->cb, cb_arg = this->cb_arg](ppu_thread& cb_ppu) -> s32
|
|
{
|
|
cb(cb_ppu, ctx_id, req_id, event_type, event_key, error_code, data_size, cb_arg);
|
|
return 0;
|
|
});
|
|
}
|
|
}
|
|
};
|
|
|
|
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;
|
|
} 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
|