diff --git a/rpcs3/Emu/NP/clans_client.cpp b/rpcs3/Emu/NP/clans_client.cpp index eb76e71130..f198cb4e63 100644 --- a/rpcs3/Emu/NP/clans_client.cpp +++ b/rpcs3/Emu/NP/clans_client.cpp @@ -19,9 +19,6 @@ const char* REQ_TYPE_SEC = "sec"; constexpr const char JID_FORMAT[] = "%s@un.br.np.playstation.net"; -const char* CLANS_SERVICE_ID = "IV0001-NPXS01001_00"; -const char* CLANS_ENTITLEMENT_ID = "NPWR00432_00"; - template <> void fmt_class_string::format(std::string& out, u64 arg) { @@ -274,39 +271,18 @@ namespace clan } std::string clans_client::getClanTicket(np::np_handler& nph) - { - if (nph.get_ticket().size() > 0) - { - std::vector ticket_bytes(1024); - uint32_t ticket_size = UINT32_MAX; - - Base64_Encode_NoNl(nph.get_ticket().data(), nph.get_ticket().size(), ticket_bytes.data(), &ticket_size); - return std::string(reinterpret_cast(ticket_bytes.data()), ticket_size); - } - + { const auto& npid = nph.get_npid(); - const char* service_id = CLANS_SERVICE_ID; - const unsigned char* cookie = nullptr; - const u32 cookie_size = 0; - const char* entitlement_id = CLANS_ENTITLEMENT_ID; - const u32 consumed_count = 0; + const char* service_id = CLANS_SERVICE_ID; + const unsigned char* cookie = nullptr; + const u32 cookie_size = 0; + const char* entitlement_id = CLANS_ENTITLEMENT_ID; + const u32 consumed_count = 0; - nph.req_ticket(0x00020001, &npid, service_id, cookie, cookie_size, entitlement_id, consumed_count); + nph.req_ticket(0x00020001, &npid, service_id, cookie, cookie_size, entitlement_id, consumed_count); - np::ticket ticket; - - // TODO: convert this to use events? - int retries = 0; - while (ticket.empty() && retries < 100) - { - ticket = nph.get_ticket(); - if (ticket.empty()) - { - std::this_thread::sleep_for(std::chrono::milliseconds(10)); - retries++; - } - } + np::ticket ticket = nph.get_clan_ticket(); if (ticket.empty()) { @@ -314,14 +290,14 @@ namespace clan return ""; } - std::vector ticket_bytes(1024); - uint32_t ticket_size = UINT32_MAX; + std::vector ticket_bytes(1024); + uint32_t ticket_size = UINT32_MAX; - Base64_Encode_NoNl(ticket.data(), ticket.size(), ticket_bytes.data(), &ticket_size); - std::string ticket_str = std::string(reinterpret_cast(ticket_bytes.data()), ticket_size); + Base64_Encode_NoNl(ticket.data(), ticket.size(), ticket_bytes.data(), &ticket_size); + std::string ticket_str = std::string(reinterpret_cast(ticket_bytes.data()), ticket_size); - return ticket_str; - } + return ticket_str; + } #pragma region Outgoing API Requests SceNpClansError clans_client::getClanList(np::np_handler& nph, s32 reqId, SceNpClansPagingRequest* paging, SceNpClansEntry* clanList, SceNpClansPagingResult* pageResult) diff --git a/rpcs3/Emu/NP/clans_client.h b/rpcs3/Emu/NP/clans_client.h index b05ab8efae..3db0243895 100644 --- a/rpcs3/Emu/NP/clans_client.h +++ b/rpcs3/Emu/NP/clans_client.h @@ -6,6 +6,9 @@ #include #include +inline const char* CLANS_ENTITLEMENT_ID = "NPWR00432_00"; +inline const char* CLANS_SERVICE_ID = "IV0001-NPXS01001_00"; + namespace clan { enum class ClanManagerOperationType diff --git a/rpcs3/Emu/NP/np_handler.cpp b/rpcs3/Emu/NP/np_handler.cpp index 30eac7f470..099f5c5b93 100644 --- a/rpcs3/Emu/NP/np_handler.cpp +++ b/rpcs3/Emu/NP/np_handler.cpp @@ -239,6 +239,25 @@ namespace np return true; } + std::string ticket::get_service_id() const + { + if (!parse_success) + { + return ""; + } + + const auto& node = nodes[0].data.data_nodes[8]; + if (node.len != SCE_NP_SERVICE_ID_SIZE) + { + return ""; + } + + // Trim null characters + const auto& vec = node.data.data_vec; + auto it = std::find(vec.begin(), vec.end(), 0); + return std::string(vec.begin(), it); + } + std::optional ticket::parse_node(std::size_t index) const { if ((index + MIN_TICKET_DATA_SIZE) > size()) @@ -1345,6 +1364,13 @@ namespace np return history; } + ticket np_handler::get_clan_ticket() + { + std::unique_lock lock(mutex_clan_ticket); + cv_clan_ticket.wait(lock, [this] { return clan_ticket_ready.load(); }); + return clan_ticket; + } + constexpr usz MAX_HISTORY_ENTRIES = 200; void np_handler::add_player_to_history(const SceNpId* npid, const char* description) diff --git a/rpcs3/Emu/NP/np_handler.h b/rpcs3/Emu/NP/np_handler.h index c7a086f224..5b8e841961 100644 --- a/rpcs3/Emu/NP/np_handler.h +++ b/rpcs3/Emu/NP/np_handler.h @@ -3,6 +3,7 @@ #include #include #include +#include #include "Emu/Memory/vm_ptr.h" #include "Emu/Cell/Modules/sceNp.h" @@ -69,6 +70,7 @@ namespace np bool empty() const; bool get_value(s32 param_id, vm::ptr param) const; + std::string get_service_id() const; private: std::optional parse_node(std::size_t index) const; @@ -253,6 +255,7 @@ namespace np // 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; + ticket get_clan_ticket(); 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); @@ -415,6 +418,12 @@ namespace np ticket current_ticket; + // Clan ticket + std::mutex mutex_clan_ticket; + std::condition_variable_any cv_clan_ticket; + atomic_t clan_ticket_ready = false; + ticket clan_ticket; + // IP & DNS info std::string hostname = "localhost"; std::array ether_address{}; diff --git a/rpcs3/Emu/NP/np_requests.cpp b/rpcs3/Emu/NP/np_requests.cpp index 23e18f1353..05fae258e3 100644 --- a/rpcs3/Emu/NP/np_requests.cpp +++ b/rpcs3/Emu/NP/np_requests.cpp @@ -1,5 +1,6 @@ #include "Emu/Cell/Modules/sceNp.h" #include "Emu/Cell/Modules/sceNp2.h" +#include "Emu/NP/clans_client.h" #include "Emu/NP/rpcn_types.h" #include "Utilities/StrFmt.h" #include "stdafx.h" @@ -866,6 +867,17 @@ namespace np current_ticket = ticket(std::move(ticket_raw)); auto ticket_size = static_cast(current_ticket.size()); + + // Clans: check if ticket belongs to the clan service. If so, store it. + if (current_ticket.get_service_id() == CLANS_SERVICE_ID) + { + std::lock_guard lock(mutex_clan_ticket); + clan_ticket = current_ticket; + clan_ticket_ready = true; + cv_clan_ticket.notify_all(); + return; + } + 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