#pragma once #include #include #include #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 data_vec; std::vector data_nodes; } data; }; struct player_history { u64 timestamp{}; std::set communication_ids; std::string description; }; class ticket { public: ticket() = default; ticket(std::vector&& raw_data); std::size_t size() const; const u8* data() const; bool empty() const; bool get_value(s32 param_id, vm::ptr param) const; private: std::optional parse_node(std::size_t index) const; void parse(); private: static constexpr std::size_t MIN_TICKET_DATA_SIZE = 4; std::vector raw_data; bool parse_success = false; u32 version{}; std::vector nodes; }; struct basic_event { s32 event = 0; SceNpUserInfo from{}; std::vector 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& 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 poolptr); void terminate_NP(); atomic_t is_netctl_init = false; atomic_t is_NP_init = false; atomic_t is_NP_Lookup_init = false; atomic_t is_NP_Score_init = false; atomic_t is_NP2_init = false; atomic_t is_NP2_Match2_init = false; atomic_t is_NP_Auth_init = false; atomic_t is_NP_TUS_init = false; // TODO: savestate atomic_t is_NP_Com2_init = false; // TODO: savestate // NP Handlers/Callbacks // Seems to be global vm::ptr manager_cb{}; // Connection status and tickets vm::ptr manager_cb_arg{}; atomic_t basic_handler_registered = false; void register_basic_handler(vm::cptr context, vm::ptr handler, vm::ptr 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 event, vm::ptr from, vm::ptr data, vm::ptr size); // Messages-related functions std::optional>> get_message(u64 id); void set_message_selected(SceNpBasicAttachmentDataId id, u64 msg_id); std::optional>> get_message_selected(SceNpBasicAttachmentDataId id); void clear_message_selected(SceNpBasicAttachmentDataId id); void send_message(const message_data& msg_data, const std::set& npids); // Those should probably be under match2 ctx vm::ptr room_event_cb{}; // Room events u16 room_event_cb_ctx = 0; vm::ptr room_event_cb_arg{}; vm::ptr room_msg_cb{}; u16 room_msg_cb_ctx = 0; vm::ptr room_msg_cb_arg{}; // Synchronous requests std::vector get_match2_server_list(SceNpMatching2ContextId); u64 get_network_time(); // Asynchronous requests u32 get_server_status(SceNpMatching2ContextId ctx_id, vm::cptr optParam, u16 server_id); u32 create_server_context(SceNpMatching2ContextId ctx_id, vm::cptr optParam, u16 server_id); u32 delete_server_context(SceNpMatching2ContextId ctx_id, vm::cptr optParam, u16 server_id); u32 get_world_list(SceNpMatching2ContextId ctx_id, vm::cptr optParam, u16 server_id); u32 create_join_room(SceNpMatching2ContextId ctx_id, vm::cptr optParam, const SceNpMatching2CreateJoinRoomRequest* req); u32 join_room(SceNpMatching2ContextId ctx_id, vm::cptr optParam, const SceNpMatching2JoinRoomRequest* req); u32 leave_room(SceNpMatching2ContextId ctx_id, vm::cptr optParam, const SceNpMatching2LeaveRoomRequest* req); u32 search_room(SceNpMatching2ContextId ctx_id, vm::cptr optParam, const SceNpMatching2SearchRoomRequest* req); u32 get_roomdata_external_list(SceNpMatching2ContextId ctx_id, vm::cptr optParam, const SceNpMatching2GetRoomDataExternalListRequest* req); u32 set_roomdata_external(SceNpMatching2ContextId ctx_id, vm::cptr optParam, const SceNpMatching2SetRoomDataExternalRequest* req); u32 get_roomdata_internal(SceNpMatching2ContextId ctx_id, vm::cptr optParam, const SceNpMatching2GetRoomDataInternalRequest* req); u32 set_roomdata_internal(SceNpMatching2ContextId ctx_id, vm::cptr optParam, const SceNpMatching2SetRoomDataInternalRequest* req); u32 get_roommemberdata_internal(SceNpMatching2ContextId ctx_id, vm::cptr optParam, const SceNpMatching2GetRoomMemberDataInternalRequest* req); u32 set_roommemberdata_internal(SceNpMatching2ContextId ctx_id, vm::cptr optParam, const SceNpMatching2SetRoomMemberDataInternalRequest* req); u32 set_userinfo(SceNpMatching2ContextId ctx_id, vm::cptr optParam, const SceNpMatching2SetUserInfoRequest* req); u32 get_ping_info(SceNpMatching2ContextId ctx_id, vm::cptr optParam, const SceNpMatching2SignalingGetPingInfoRequest* req); u32 send_room_message(SceNpMatching2ContextId ctx_id, vm::cptr optParam, const SceNpMatching2SendRoomMessageRequest* req); u32 get_lobby_info_list(SceNpMatching2ContextId ctx_id, vm::cptr 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 buf, vm::ptr size, vm::ptr event); error_code get_result_gui(vm::ptr buf, vm::ptr size, vm::ptr event); error_code create_room_gui(u32 ctx_id, vm::cptr communicationId, vm::cptr attr, vm::ptr handler, vm::ptr arg); error_code join_room_gui(u32 ctx_id, vm::ptr roomid, vm::ptr handler, vm::ptr arg); error_code leave_room_gui(u32 ctx_id, vm::cptr roomid); error_code get_room_list_gui(u32 ctx_id, vm::cptr communicationId, vm::ptr range, vm::ptr cond, vm::ptr attr, vm::ptr handler, vm::ptr arg, bool limit); error_code set_room_search_flag_gui(u32 ctx_id, vm::ptr lobby_id, vm::ptr room_id, s32 flag); error_code get_room_search_flag_gui(u32 ctx_id, vm::ptr lobby_id, vm::ptr room_id); error_code set_room_info_gui(u32 ctx_id, vm::ptr lobby_id, vm::ptr room_id, vm::ptr attr); error_code get_room_info_gui(u32 ctx_id, vm::ptr lobby_id, vm::ptr room_id, vm::ptr attr); error_code quickmatch_gui(u32 ctx_id, vm::cptr communicationId, vm::cptr cond, s32 available_num, s32 timeout, vm::ptr handler, vm::ptr arg); error_code searchjoin_gui(u32 ctx_id, vm::cptr communicationId, vm::cptr cond, vm::cptr attr, vm::ptr handler, vm::ptr arg); void set_current_gui_ctx_id(u32 id); // Score requests void transaction_async_handler(std::unique_lock lock, const shared_ptr& trans_ctx, u32 req_id, bool async); void get_board_infos(shared_ptr& trans_ctx, SceNpScoreBoardId boardId, vm::ptr boardInfo, bool async); void record_score(shared_ptr& trans_ctx, SceNpScoreBoardId boardId, SceNpScoreValue score, vm::cptr scoreComment, const u8* data, u32 data_size, vm::ptr tmpRank, bool async); void record_score_data(shared_ptr& trans_ctx, SceNpScoreBoardId boardId, SceNpScoreValue score, u32 totalSize, u32 sendSize, const u8* score_data, bool async); void get_score_data(shared_ptr& trans_ctx, SceNpScoreBoardId boardId, const SceNpId& npId, vm::ptr totalSize, u32 recvSize, vm::ptr score_data, bool async); void get_score_range(shared_ptr& trans_ctx, SceNpScoreBoardId boardId, SceNpScoreRankNumber startSerialRank, vm::ptr rankArray, u32 rankArraySize, vm::ptr commentArray, u32 commentArraySize, vm::ptr infoArray, u32 infoArraySize, u32 arrayNum, vm::ptr lastSortDate, vm::ptr totalRecord, bool async, bool deprecated); void get_score_npid(shared_ptr& trans_ctx, SceNpScoreBoardId boardId, const std::vector>& npid_vec, vm::ptr rankArray, u32 rankArraySize, vm::ptr commentArray, u32 commentArraySize, vm::ptr infoArray, u32 infoArraySize, u32 arrayNum, vm::ptr lastSortDate, vm::ptr totalRecord, bool async, bool deprecated); void get_score_friend(shared_ptr& trans_ctx, SceNpScoreBoardId boardId, bool include_self, vm::ptr rankArray, u32 rankArraySize, vm::ptr commentArray, u32 commentArraySize, vm::ptr infoArray, u32 infoArraySize, u32 arrayNum, vm::ptr lastSortDate, vm::ptr totalRecord, bool async, bool deprecated); // TUS requests void tus_set_multislot_variable(shared_ptr& trans_ctx, const SceNpOnlineId& targetNpId, vm::cptr slotIdArray, vm::cptr variableArray, s32 arrayNum, bool vuser, bool async); void tus_get_multislot_variable(shared_ptr& trans_ctx, const SceNpOnlineId& targetNpId, vm::cptr slotIdArray, vm::ptr variableArray, s32 arrayNum, bool vuser, bool async); void tus_get_multiuser_variable(shared_ptr& trans_ctx, std::vector targetNpIdArray, SceNpTusSlotId slotId, vm::ptr variableArray, s32 arrayNum, bool vuser, bool async); void tus_get_friends_variable(shared_ptr& trans_ctx, SceNpTusSlotId slotId, s32 includeSelf, s32 sortType, vm::ptr variableArray,s32 arrayNum, bool async); void tus_add_and_get_variable(shared_ptr& trans_ctx, const SceNpOnlineId& targetNpId, SceNpTusSlotId slotId, s64 inVariable, vm::ptr outVariable, vm::ptr option, bool vuser, bool async); void tus_try_and_set_variable(shared_ptr& trans_ctx, const SceNpOnlineId& targetNpId, SceNpTusSlotId slotId, s32 opeType, s64 variable, vm::ptr resultVariable, vm::ptr option, bool vuser, bool async); void tus_delete_multislot_variable(shared_ptr& trans_ctx, const SceNpOnlineId& targetNpId, vm::cptr slotIdArray, s32 arrayNum, bool vuser, bool async); void tus_set_data(shared_ptr& trans_ctx, const SceNpOnlineId& targetNpId, SceNpTusSlotId slotId, u32 totalSize, u32 sendSize, vm::cptr data, vm::cptr info, vm::ptr option, bool vuser, bool async); void tus_get_data(shared_ptr& trans_ctx, const SceNpOnlineId& targetNpId, SceNpTusSlotId slotId, vm::ptr dataStatus, vm::ptr data, u32 recvSize, bool vuser, bool async); void tus_get_multislot_data_status(shared_ptr& trans_ctx, const SceNpOnlineId& targetNpId, vm::cptr slotIdArray, vm::ptr statusArray, s32 arrayNum, bool vuser, bool async); void tus_get_multiuser_data_status(shared_ptr& trans_ctx, std::vector targetNpIdArray, SceNpTusSlotId slotId, vm::ptr statusArray, s32 arrayNum, bool vuser, bool async); void tus_get_friends_data_status(shared_ptr& trans_ctx, SceNpTusSlotId slotId, s32 includeSelf, s32 sortType, vm::ptr statusArray, s32 arrayNum, bool async); void tus_delete_multislot_data(shared_ptr& trans_ctx, const SceNpOnlineId& targetNpId, vm::cptr slotIdArray, s32 arrayNum, bool vuser, bool async); // Local functions std::pair> local_get_npid(u64 room_id, u16 member_id); std::pair> local_get_room_slots(SceNpMatching2RoomId room_id); std::pair> local_get_room_password(SceNpMatching2RoomId room_id); std::pair> 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& 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 room_id, vm::ptr buflen, vm::ptr buf); // Friend stuff u32 get_num_friends(); u32 get_num_blocks(); std::pair> get_friend_by_index(u32 index); void set_presence(std::optional status, std::optional> data); template error_code get_friend_presence_by_index(u32 index, SceNpUserInfo* user, T* pres); template 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 custom_menu_handler{}; vm::ptr custom_menu_user_arg{}; std::vector custom_menu_actions; SceNpCustomMenuIndexArray custom_menu_activation{}; std::vector 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 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 cb; vm::ptr 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 optParam, SceNpMatching2Event event_type); std::optional take_pending_request(u32 req_id); private: shared_mutex mutex_pending_requests; std::unordered_map pending_requests; shared_mutex mutex_pending_sign_infos_requests; std::unordered_map pending_sign_infos_requests; shared_mutex mutex_queue_basic_events; std::queue queue_basic_events; bool m_inited_np_handler_dependencies = false; // Basic event handler; struct { shared_mutex mutex; SceNpCommunicationId context{}; vm::ptr handler_func; vm::ptr 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 ether_address{}; be_t local_ip_addr{}; be_t public_ip_addr{}; be_t dns_ip = 0x08080808; be_t 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 cached_cj_password; cache_manager np_cache; gui_cache_manager gui_cache; // Messages related std::optional selected_invite_id{}; std::optional selected_message_id{}; // Misc s64 network_time_offset = 0; // Requests(reqEventKey : data) shared_mutex mutex_match2_req_results; std::unordered_map match2_req_results; atomic_t match2_low_reqid_cnt = 1; atomic_t 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(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, 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> async_transactions; // (req_id, transaction_ctx) // RPCN shared_mutex mutex_rpcn; std::shared_ptr rpcn; std::shared_ptr 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 pr_data; atomic_t 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 players_history; // npid / history struct { shared_mutex mutex; std::map 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 take_pending_gui_request(u32 req_id); shared_mutex mutex_quickmatching; std::map pending_quickmatching; }; } // namespace np