From eabd04d35d8814f1674a7350c9ba3b034a295827 Mon Sep 17 00:00:00 2001 From: metr1k-91 Date: Mon, 6 Jul 2026 15:49:29 -0500 Subject: [PATCH] Matching P10 - Fixups (#4680) Fixed onlineid terming 1 character in 16 char names Fixed default request callback opt calls not appropriately staying after the first callback misc other struct changes. --- src/core/libraries/np/np_handler.cpp | 6 +- .../np/np_matching2/np_matching2.cpp | 36 ++++-- .../np/np_matching2/np_matching2_internal.cpp | 108 +++++++++++++----- .../np/np_matching2/np_matching2_internal.h | 14 +++ .../np/np_matching2/np_matching2_mm.cpp | 40 +++++-- .../np/np_matching2/np_matching2_mm.h | 2 +- .../np_matching2/np_matching2_signaling.cpp | 14 ++- .../np/np_signaling/np_signaling_state.cpp | 5 +- src/core/libraries/np/np_types.h | 20 +++- 9 files changed, 182 insertions(+), 63 deletions(-) diff --git a/src/core/libraries/np/np_handler.cpp b/src/core/libraries/np/np_handler.cpp index 9a9c048a7..3fc848d77 100644 --- a/src/core/libraries/np/np_handler.cpp +++ b/src/core/libraries/np/np_handler.cpp @@ -211,7 +211,7 @@ bool NpHandler::ConnectUser(s32 user_id, const std::string& host, u16 port, cons // Build OrbisNpId { OrbisNpId np_id{}; - strncpy(np_id.handle.data, npid.c_str(), sizeof(np_id.handle.data) - 1); + SetNpId(np_id, npid); std::lock_guard lock(m_mutex_clients); m_np_ids[user_id] = np_id; m_clients[user_id] = std::move(client); @@ -704,11 +704,11 @@ void NpHandler::OnWebApiPushEvent(s32 user_id, const ShadNet::NotifyWebApiPushEv ev.data = n.data; if (!n.fromNpid.empty()) { ev.hasFrom = true; - std::strncpy(ev.fromOnlineId.data, n.fromNpid.c_str(), sizeof(ev.fromOnlineId.data) - 1); + SetNpOnlineId(ev.fromOnlineId, n.fromNpid); } if (!n.toNpid.empty()) { ev.hasTo = true; - std::strncpy(ev.toOnlineId.data, n.toNpid.c_str(), sizeof(ev.toOnlineId.data) - 1); + SetNpOnlineId(ev.toOnlineId, n.toNpid); } ev.extdData = n.extdData; // extended-data (key,value) pairs -> dispatched as pExtdData NpWebApi::EnqueuePushEvent(ev); diff --git a/src/core/libraries/np/np_matching2/np_matching2.cpp b/src/core/libraries/np/np_matching2/np_matching2.cpp index a5a2cfb2e..109ddfc31 100644 --- a/src/core/libraries/np/np_matching2/np_matching2.cpp +++ b/src/core/libraries/np/np_matching2/np_matching2.cpp @@ -2,7 +2,9 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include +#include #include +#include #include "common/logging/log.h" #include "core/emulator_settings.h" @@ -245,7 +247,11 @@ int PS4_SYSV_ABI sceNpMatching2ContextStop(OrbisNpMatching2ContextId ctxId) { return rc; } - MmContextStop(ctxId); + const s32 submit_rc = MmContextStop(ctxId); + if (submit_rc != ORBIS_OK) { + ContextManager::Instance().CompleteStop(ctxId); + return submit_rc; + } return ORBIS_OK; } @@ -311,6 +317,11 @@ int PS4_SYSV_ABI sceNpMatching2SetDefaultRequestOptParam( return ORBIS_NP_MATCHING2_ERROR_INVALID_CONTEXT_ID; } + LOG_INFO(Lib_NpMatching2, + "SetDefaultRequestOptParam: ctx={} opt={} callback={:#x} arg={} timeout={} appId={}", + ctxId, fmt::ptr(requestOpt), reinterpret_cast(requestOpt->callback), + fmt::ptr(requestOpt->arg), requestOpt->timeout, requestOpt->appId); + ctx->default_request_callback = requestOpt->callback; ctx->default_request_callback_arg = requestOpt->arg; @@ -570,8 +581,7 @@ s32 PS4_SYSV_ABI sceNpMatching2SignalingGetConnectionStatus(OrbisNpMatching2Cont if (member_it != room_it->second.members.end()) { pi.addr = member_it->second.addr; pi.port = member_it->second.port; - std::strncpy(pi.online_id.data, member_it->second.np_id.handle.data, - sizeof(pi.online_id.data) - 1); + pi.online_id = member_it->second.np_id.handle; } peer_it = ctx->peers.emplace(memberId, pi).first; } @@ -750,8 +760,9 @@ int PS4_SYSV_ABI sceNpMatching2GetRoomDataInternal( ev.req_id = reqId; ev.req_event = ORBIS_NP_MATCHING2_REQUEST_EVENT_GET_ROOM_DATA_INTERNAL; ev.error_code = 0; - ev.request_cb = ctx->default_request_callback; - ev.request_cb_arg = ctx->default_request_callback_arg; + const RequestCallbackInfo request_cb = ConsumeRequestCallback(ctx); + ev.request_cb = request_cb.callback; + ev.request_cb_arg = request_cb.arg; ev.request_data = request_data; ScheduleEvent(std::move(ev)); return ORBIS_OK; @@ -971,9 +982,10 @@ int PS4_SYSV_ABI sceNpMatching2SignalingGetPingInfo(OrbisNpMatching2ContextId ct const OrbisNpMatching2RequestId request_id = AllocRequestId(); *reqId = request_id; - const bool room_found = ctx->room_cache.find(request->roomId) != ctx->room_cache.end(); - void* request_data = - room_found ? BuildSignalingGetPingInfoPayload(*ctx, request->roomId) : nullptr; + auto request_payload_owner = std::make_shared(); + ctx->request_payload_override = request_payload_owner.get(); + void* request_data = BuildSignalingGetPingInfoPayload(*ctx, request->roomId); + ctx->request_payload_override = nullptr; PendingEvent ev{}; ev.type = PendingEvent::REQUEST_CB; @@ -981,10 +993,12 @@ int PS4_SYSV_ABI sceNpMatching2SignalingGetPingInfo(OrbisNpMatching2ContextId ct ev.fire_at = std::chrono::steady_clock::now(); ev.req_id = request_id; ev.req_event = ORBIS_NP_MATCHING2_REQUEST_EVENT_SIGNALING_GET_PING_INFO; - ev.error_code = room_found ? ORBIS_OK : ORBIS_NP_MATCHING2_ERROR_ROOM_NOT_FOUND; - ev.request_cb = ctx->default_request_callback; - ev.request_cb_arg = ctx->default_request_callback_arg; + ev.error_code = ORBIS_OK; + const RequestCallbackInfo request_cb = ConsumeRequestCallback(ctx); + ev.request_cb = request_cb.callback; + ev.request_cb_arg = request_cb.arg; ev.request_data = request_data; + ev.request_payload_owner = std::move(request_payload_owner); ScheduleEvent(std::move(ev)); return ORBIS_OK; } diff --git a/src/core/libraries/np/np_matching2/np_matching2_internal.cpp b/src/core/libraries/np/np_matching2/np_matching2_internal.cpp index 54bf6c05f..3fd58cd93 100644 --- a/src/core/libraries/np/np_matching2/np_matching2_internal.cpp +++ b/src/core/libraries/np/np_matching2/np_matching2_internal.cpp @@ -20,6 +20,10 @@ NpMatching2State g_state; namespace { +CallbackPayload& RequestPayload(ContextObject& ctx) { + return ctx.request_payload_override ? *ctx.request_payload_override : ctx.request_payload; +} + u32 IpStringToAddr(std::string_view ip) { u32 a, b, c, d; if (std::sscanf(std::string(ip).c_str(), "%u.%u.%u.%u", &a, &b, &c, &d) != 4) { @@ -60,7 +64,7 @@ void ReserveExternalRoomPayloadStorage(CallbackPayload& p, const Reply& resp) { void BuildCreateJoinRoomPayloadCommon(ContextObject& ctx, const shadnet::CreateJoinRoomResponse& resp) { - CallbackPayload& p = ctx.request_payload; + CallbackPayload& p = RequestPayload(ctx); const auto& rd = resp.room_data(); p.room_groups.resize(rd.groups_size()); @@ -172,7 +176,7 @@ void BuildCreateJoinRoomPayloadCommon(ContextObject& ctx, mc.join_date = m.join_date(); mc.addr = IpStringToAddr(m.addr()); mc.port = Libraries::Net::sceNetHtons(static_cast(m.port())); - std::strncpy(mc.np_id.handle.data, m.npid().c_str(), sizeof(mc.np_id.handle.data) - 1); + SetNpId(mc.np_id, m.npid()); mc.account_id = static_cast(m.account_id()); mc.platform = static_cast(m.platform()); for (const auto& a : m.bin_attrs_internal()) { @@ -186,7 +190,7 @@ void BuildCreateJoinRoomPayloadCommon(ContextObject& ctx, peer.member_id = mc.member_id; peer.addr = mc.addr; peer.port = mc.port; - std::strncpy(peer.online_id.data, m.npid().c_str(), sizeof(peer.online_id.data) - 1); + SetNpOnlineId(peer.online_id, m.npid()); ctx.peers[mc.member_id] = peer; } } @@ -227,7 +231,7 @@ OrbisNpMatching2RoomMemberBinAttrInternal* AppendMemberBinAttrs( } void* BuildCreateJoinRoomPayload(ContextObject& ctx, const shadnet::CreateJoinRoomResponse& resp) { - CallbackPayload& p = ctx.request_payload; + CallbackPayload& p = RequestPayload(ctx); p.Reset(); BuildCreateJoinRoomPayloadCommon(ctx, resp); @@ -240,7 +244,7 @@ void* BuildCreateJoinRoomPayload(ContextObject& ctx, const shadnet::CreateJoinRo dst = OrbisNpMatching2RoomMemberDataInternal{}; dst.next = (i + 1 < member_count) ? &p.member_data[i + 1] : nullptr; dst.joinDate = m.join_date(); - std::strncpy(dst.npId.handle.data, m.npid().c_str(), sizeof(dst.npId.handle.data) - 1); + SetNpId(dst.npId, m.npid()); dst.memberId = static_cast(m.member_id()); dst.teamId = static_cast(m.team_id()); dst.natType = static_cast(m.nat_type()); @@ -274,7 +278,7 @@ void* BuildCreateJoinRoomPayload(ContextObject& ctx, const shadnet::CreateJoinRo } void* BuildCreateJoinRoomPayloadA(ContextObject& ctx, const shadnet::CreateJoinRoomResponse& resp) { - CallbackPayload& p = ctx.request_payload; + CallbackPayload& p = RequestPayload(ctx); p.Reset(); BuildCreateJoinRoomPayloadCommon(ctx, resp); @@ -289,7 +293,7 @@ void* BuildCreateJoinRoomPayloadA(ContextObject& ctx, const shadnet::CreateJoinR dst.joinDateTicks.tick = m.join_date(); dst.user.accountId = static_cast(m.account_id()); dst.user.platform = static_cast(m.platform()); - std::strncpy(dst.onlineId.data, m.npid().c_str(), sizeof(dst.onlineId.data) - 1); + SetNpOnlineId(dst.onlineId, m.npid()); dst.memberId = static_cast(m.member_id()); dst.teamId = static_cast(m.team_id()); dst.natType = static_cast(m.nat_type()); @@ -322,7 +326,7 @@ void* BuildCreateJoinRoomPayloadA(ContextObject& ctx, const shadnet::CreateJoinR } void* BuildLeaveRoomPayload(ContextObject& ctx, const shadnet::LeaveRoomReply& resp) { - CallbackPayload& p = ctx.request_payload; + CallbackPayload& p = RequestPayload(ctx); p.Reset(); p.leave_room_response = std::make_unique(); @@ -341,7 +345,7 @@ void* BuildLeaveRoomPayload(ContextObject& ctx, const shadnet::LeaveRoomReply& r } void* BuildGetWorldInfoListPayload(ContextObject& ctx, const shadnet::GetWorldInfoListReply& resp) { - CallbackPayload& p = ctx.request_payload; + CallbackPayload& p = RequestPayload(ctx); p.Reset(); p.world_list.resize(resp.worlds_size()); @@ -369,7 +373,7 @@ void* BuildGetWorldInfoListPayload(ContextObject& ctx, const shadnet::GetWorldIn } void* BuildSearchRoomPayload(ContextObject& ctx, const shadnet::SearchRoomReply& resp) { - CallbackPayload& p = ctx.request_payload; + CallbackPayload& p = RequestPayload(ctx); p.Reset(); ReserveExternalRoomPayloadStorage(p, resp); @@ -397,7 +401,7 @@ void* BuildSearchRoomPayload(ContextObject& ctx, const shadnet::SearchRoomReply& if (!r.owner_npid().empty()) { auto& npid = p.ext_owner_npids.emplace_back(); npid = Libraries::Np::OrbisNpId{}; - std::strncpy(npid.handle.data, r.owner_npid().c_str(), sizeof(npid.handle.data) - 1); + SetNpId(npid, r.owner_npid()); dst.ownerNpId = &npid; } @@ -474,7 +478,7 @@ void* BuildSearchRoomPayload(ContextObject& ctx, const shadnet::SearchRoomReply& } void* BuildSearchRoomPayloadA(ContextObject& ctx, const shadnet::SearchRoomReply& resp) { - CallbackPayload& p = ctx.request_payload; + CallbackPayload& p = RequestPayload(ctx); p.Reset(); ReserveExternalRoomPayloadStorage(p, resp); @@ -500,8 +504,7 @@ void* BuildSearchRoomPayloadA(ContextObject& ctx, const shadnet::SearchRoomReply dst.openPrivateSlots = static_cast(r.open_private_slots()); if (!r.owner_npid().empty()) { - std::strncpy(dst.ownerOnlineId.data, r.owner_npid().c_str(), - sizeof(dst.ownerOnlineId.data) - 1); + SetNpOnlineId(dst.ownerOnlineId, r.owner_npid()); } dst.owner.accountId = static_cast(r.owner_account_id()); dst.owner.platform = static_cast(r.owner_platform()); @@ -580,7 +583,7 @@ void* BuildSearchRoomPayloadA(ContextObject& ctx, const shadnet::SearchRoomReply void* BuildGetRoomDataExternalListPayload(ContextObject& ctx, const shadnet::GetRoomDataExternalListReply& resp) { - CallbackPayload& p = ctx.request_payload; + CallbackPayload& p = RequestPayload(ctx); p.Reset(); ReserveExternalRoomPayloadStorage(p, resp); @@ -608,7 +611,7 @@ void* BuildGetRoomDataExternalListPayload(ContextObject& ctx, if (!r.owner_npid().empty()) { auto& npid = p.ext_owner_npids.emplace_back(); npid = Libraries::Np::OrbisNpId{}; - std::strncpy(npid.handle.data, r.owner_npid().c_str(), sizeof(npid.handle.data) - 1); + SetNpId(npid, r.owner_npid()); dst.ownerNpId = &npid; } @@ -685,7 +688,7 @@ void* BuildGetRoomDataExternalListPayload(ContextObject& ctx, void* BuildGetRoomDataExternalListPayloadA(ContextObject& ctx, const shadnet::GetRoomDataExternalListReply& resp) { - CallbackPayload& p = ctx.request_payload; + CallbackPayload& p = RequestPayload(ctx); p.Reset(); ReserveExternalRoomPayloadStorage(p, resp); @@ -711,8 +714,7 @@ void* BuildGetRoomDataExternalListPayloadA(ContextObject& ctx, dst.openPrivateSlots = static_cast(r.open_private_slots()); if (!r.owner_npid().empty()) { - std::strncpy(dst.ownerOnlineId.data, r.owner_npid().c_str(), - sizeof(dst.ownerOnlineId.data) - 1); + SetNpOnlineId(dst.ownerOnlineId, r.owner_npid()); } dst.owner.accountId = static_cast(r.owner_account_id()); dst.owner.platform = static_cast(r.owner_platform()); @@ -790,7 +792,7 @@ void* BuildGetRoomDataExternalListPayloadA(ContextObject& ctx, void* BuildGetRoomMemberDataExternalListPayload( ContextObject& ctx, const shadnet::GetRoomMemberDataExternalListReply& resp) { - CallbackPayload& p = ctx.request_payload; + CallbackPayload& p = RequestPayload(ctx); p.Reset(); const int member_count = resp.members_size(); @@ -800,7 +802,7 @@ void* BuildGetRoomMemberDataExternalListPayload( auto& dst = p.member_data_external[i]; dst = OrbisNpMatching2RoomMemberDataExternal{}; dst.next = (i + 1 < member_count) ? &p.member_data_external[i + 1] : nullptr; - std::strncpy(dst.npId.handle.data, src.npid().c_str(), sizeof(dst.npId.handle.data) - 1); + SetNpId(dst.npId, src.npid()); dst.joinDate.tick = src.join_date(); dst.role = static_cast(src.role()); } @@ -819,7 +821,7 @@ void* BuildGetRoomMemberDataExternalListPayload( void* BuildGetRoomMemberDataExternalListPayloadA( ContextObject& ctx, const shadnet::GetRoomMemberDataExternalListReply& resp) { - CallbackPayload& p = ctx.request_payload; + CallbackPayload& p = RequestPayload(ctx); p.Reset(); const int member_count = resp.members_size(); @@ -831,7 +833,7 @@ void* BuildGetRoomMemberDataExternalListPayloadA( dst.next = (i + 1 < member_count) ? &p.member_data_external_a[i + 1] : nullptr; dst.user.accountId = static_cast(src.account_id()); dst.user.platform = static_cast(src.platform()); - std::strncpy(dst.onlineId.data, src.npid().c_str(), sizeof(dst.onlineId.data) - 1); + SetNpOnlineId(dst.onlineId, src.npid()); dst.joinDate.tick = src.join_date(); dst.role = static_cast(src.role()); } @@ -849,7 +851,7 @@ void* BuildGetRoomMemberDataExternalListPayloadA( } void* BuildGetUserInfoListPayload(ContextObject& ctx, const shadnet::GetUserInfoListReply& resp) { - CallbackPayload& p = ctx.request_payload; + CallbackPayload& p = RequestPayload(ctx); p.Reset(); size_t total_bin_attrs = 0; @@ -866,7 +868,7 @@ void* BuildGetUserInfoListPayload(ContextObject& ctx, const shadnet::GetUserInfo auto& dst = p.user_info[i]; dst = OrbisNpMatching2UserInfo{}; dst.next = (i + 1 < user_count) ? &p.user_info[i + 1] : nullptr; - std::strncpy(dst.npId.handle.data, u.npid().c_str(), sizeof(dst.npId.handle.data) - 1); + SetNpId(dst.npId, u.npid()); if (u.user_bin_attrs_size() > 0) { OrbisNpMatching2BinAttr* first = nullptr; @@ -899,7 +901,7 @@ void* BuildGetUserInfoListPayload(ContextObject& ctx, const shadnet::GetUserInfo } void* BuildGetUserInfoListPayloadA(ContextObject& ctx, const shadnet::GetUserInfoListReply& resp) { - CallbackPayload& p = ctx.request_payload; + CallbackPayload& p = RequestPayload(ctx); p.Reset(); size_t total_bin_attrs = 0; @@ -916,7 +918,7 @@ void* BuildGetUserInfoListPayloadA(ContextObject& ctx, const shadnet::GetUserInf auto& dst = p.user_info_a[i]; dst = OrbisNpMatching2UserInfoA{}; dst.next = (i + 1 < user_count) ? &p.user_info_a[i + 1] : nullptr; - std::strncpy(dst.userOnlineId.data, u.npid().c_str(), sizeof(dst.userOnlineId.data) - 1); + SetNpOnlineId(dst.userOnlineId, u.npid()); dst.user.accountId = static_cast(u.account_id()); dst.user.platform = static_cast(u.platform()); @@ -957,7 +959,7 @@ void* BuildGetRoomDataInternalPayload(ContextObject& ctx, OrbisNpMatching2RoomId } const RoomCache& rc = rc_it->second; - CallbackPayload& p = ctx.request_payload; + CallbackPayload& p = RequestPayload(ctx); p.Reset(); p.room_groups.clear(); @@ -1106,15 +1108,36 @@ ContextObject* ContextManager::Get(OrbisNpMatching2ContextId ctx_id) { bool ContextManager::Destroy(OrbisNpMatching2ContextId ctx_id) { std::lock_guard lock(m_mutex); - if (!GetLocked(ctx_id)) { + ContextObject* ctx = GetLocked(ctx_id); + if (!ctx) { return false; } + if (ctx->stop_pending) { + ctx->destroy_pending = true; + LOG_DEBUG(Lib_NpMatching2, "context destroy deferred until stop callback: id={}", ctx_id); + return true; + } m_contexts[ctx_id].Reset(); m_used[ctx_id] = false; LOG_DEBUG(Lib_NpMatching2, "context destroyed: id={}", ctx_id); return true; } +void ContextManager::CompleteStop(OrbisNpMatching2ContextId ctx_id) { + std::lock_guard lock(m_mutex); + ContextObject* ctx = GetLocked(ctx_id); + if (!ctx) { + return; + } + ctx->stop_pending = false; + if (!ctx->destroy_pending) { + return; + } + m_contexts[ctx_id].Reset(); + m_used[ctx_id] = false; + LOG_DEBUG(Lib_NpMatching2, "context destroyed after stop callback: id={}", ctx_id); +} + s32 ContextManager::Start(OrbisNpMatching2ContextId ctx_id) { std::lock_guard lock(m_mutex); ContextObject* ctx = GetLocked(ctx_id); @@ -1125,6 +1148,8 @@ s32 ContextManager::Start(OrbisNpMatching2ContextId ctx_id) { return ORBIS_NP_MATCHING2_ERROR_CONTEXT_ALREADY_STARTED; } ctx->started = true; + ctx->stop_pending = false; + ctx->destroy_pending = false; LOG_DEBUG(Lib_NpMatching2, "context started: id={}", ctx_id); return ORBIS_OK; } @@ -1139,6 +1164,7 @@ s32 ContextManager::Stop(OrbisNpMatching2ContextId ctx_id) { return ORBIS_NP_MATCHING2_ERROR_CONTEXT_NOT_STARTED; } ctx->started = false; + ctx->stop_pending = true; LOG_DEBUG(Lib_NpMatching2, "context stopped: id={}", ctx_id); return ORBIS_OK; } @@ -1186,12 +1212,29 @@ void SetInitialized(bool initialized) { } void StoreRequestCallback(ContextObject* ctx, const OrbisNpMatching2RequestOptParam* requestOpt) { + ctx->per_request_callback = nullptr; + ctx->per_request_callback_arg = nullptr; if (requestOpt && requestOpt->callback) { - ctx->default_request_callback = requestOpt->callback; - ctx->default_request_callback_arg = requestOpt->arg; + ctx->per_request_callback = requestOpt->callback; + ctx->per_request_callback_arg = requestOpt->arg; } } +RequestCallbackInfo ConsumeRequestCallback(ContextObject* ctx) { + RequestCallbackInfo cb{}; + if (ctx->per_request_callback) { + cb.callback = ctx->per_request_callback; + cb.arg = ctx->per_request_callback_arg; + ctx->per_request_callback = nullptr; + ctx->per_request_callback_arg = nullptr; + return cb; + } + + cb.callback = ctx->default_request_callback; + cb.arg = ctx->default_request_callback_arg; + return cb; +} + namespace { void FireEvent(const PendingEvent& ev) { @@ -1213,6 +1256,9 @@ void FireEvent(const PendingEvent& ev) { LOG_WARNING(Lib_NpMatching2, "callback CONTEXT ctx={} event={:#x} SKIPPED: no callback", ev.ctx_id, static_cast(ev.ctx_event)); } + if (ev.ctx_event == ORBIS_NP_MATCHING2_CONTEXT_EVENT_STOPPED) { + ContextManager::Instance().CompleteStop(ev.ctx_id); + } break; case PendingEvent::REQUEST_CB: if (ev.request_cb) { diff --git a/src/core/libraries/np/np_matching2/np_matching2_internal.h b/src/core/libraries/np/np_matching2/np_matching2_internal.h index fdfa8077a..3c76ed4a0 100644 --- a/src/core/libraries/np/np_matching2/np_matching2_internal.h +++ b/src/core/libraries/np/np_matching2/np_matching2_internal.h @@ -203,6 +203,8 @@ struct CallbackPayload { struct ContextObject { OrbisNpMatching2ContextId ctx_id = 0; bool started = false; + bool stop_pending = false; + bool destroy_pending = false; bool a_variant = false; OrbisNpMatching2ServerId server_id = 1; @@ -228,6 +230,7 @@ struct ContextObject { std::map room_cache; CallbackPayload request_payload; + CallbackPayload* request_payload_override = nullptr; CallbackPayload room_event_payload; OrbisNpMatching2ContextCallback context_callback = nullptr; @@ -250,6 +253,8 @@ struct ContextObject { void Reset() { ctx_id = 0; started = false; + stop_pending = false; + destroy_pending = false; a_variant = false; server_id = 1; service_label = 0; @@ -268,6 +273,7 @@ struct ContextObject { peers.clear(); room_cache.clear(); request_payload.Reset(); + request_payload_override = nullptr; room_event_payload.Reset(); context_callback = nullptr; context_callback_arg = nullptr; @@ -288,6 +294,11 @@ struct ContextObject { } }; +struct RequestCallbackInfo { + OrbisNpMatching2RequestCallback callback = nullptr; + void* arg = nullptr; +}; + class ContextManager { public: static constexpr u32 kMaxContexts = 10; @@ -300,6 +311,7 @@ public: bool Check(OrbisNpMatching2ContextId ctx_id); ContextObject* Get(OrbisNpMatching2ContextId ctx_id); bool Destroy(OrbisNpMatching2ContextId ctx_id); + void CompleteStop(OrbisNpMatching2ContextId ctx_id); s32 Start(OrbisNpMatching2ContextId ctx_id); s32 Stop(OrbisNpMatching2ContextId ctx_id); @@ -344,6 +356,7 @@ struct PendingEvent { OrbisNpMatching2RequestCallback request_cb = nullptr; void* request_cb_arg = nullptr; void* request_data = nullptr; + std::shared_ptr request_payload_owner; OrbisNpMatching2RoomId room_id = 0; OrbisNpMatching2RoomMemberId member_id = 0; @@ -382,6 +395,7 @@ OrbisNpMatching2RequestId AllocRequestId(); bool IsInitialized(); void SetInitialized(bool initialized); void StoreRequestCallback(ContextObject* ctx, const OrbisNpMatching2RequestOptParam* requestOpt); +RequestCallbackInfo ConsumeRequestCallback(ContextObject* ctx); void* BuildCreateJoinRoomPayload(ContextObject& ctx, const shadnet::CreateJoinRoomResponse& resp); void* BuildCreateJoinRoomPayloadA(ContextObject& ctx, const shadnet::CreateJoinRoomResponse& resp); diff --git a/src/core/libraries/np/np_matching2/np_matching2_mm.cpp b/src/core/libraries/np/np_matching2/np_matching2_mm.cpp index e7d6c3f22..db936cd34 100644 --- a/src/core/libraries/np/np_matching2/np_matching2_mm.cpp +++ b/src/core/libraries/np/np_matching2/np_matching2_mm.cpp @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -30,6 +31,8 @@ struct PendingRequest { OrbisNpMatching2RequestId req_id = 0; OrbisNpMatching2Event req_event{}; bool a_variant = false; + OrbisNpMatching2RequestCallback request_cb = nullptr; + void* request_cb_arg = nullptr; }; struct MmClientState { @@ -160,8 +163,11 @@ void DispatchRequestComplete(const PendingRequest& pr, ShadNet::ErrorType error, } void* request_data = nullptr; + std::shared_ptr request_payload_owner; if (error_code == 0) { + request_payload_owner = std::make_shared(); + ctx->request_payload_override = request_payload_owner.get(); const std::string proto = ExtractProtoBytes(body); if (pr.req_event == ORBIS_NP_MATCHING2_REQUEST_EVENT_CREATE_JOIN_ROOM || pr.req_event == ORBIS_NP_MATCHING2_REQUEST_EVENT_CREATE_JOIN_ROOM_A) { @@ -221,6 +227,7 @@ void DispatchRequestComplete(const PendingRequest& pr, ShadNet::ErrorType error, : BuildGetUserInfoListPayload(*ctx, reply); } } + ctx->request_payload_override = nullptr; } PendingEvent ev{}; @@ -230,9 +237,10 @@ void DispatchRequestComplete(const PendingRequest& pr, ShadNet::ErrorType error, ev.req_id = pr.req_id; ev.req_event = pr.req_event; ev.error_code = error_code; - ev.request_cb = ctx->default_request_callback; - ev.request_cb_arg = ctx->default_request_callback_arg; + ev.request_cb = pr.request_cb; + ev.request_cb_arg = pr.request_cb_arg; ev.request_data = request_data; + ev.request_payload_owner = std::move(request_payload_owner); ScheduleEvent(std::move(ev)); if (error_code == 0 && (pr.req_event == ORBIS_NP_MATCHING2_REQUEST_EVENT_JOIN_ROOM || @@ -284,7 +292,7 @@ void BuildMemberUpdate(CallbackPayload& p, const RoomCache& rc, const MemberCach m.joinDateTicks.tick = mc.join_date; m.user.accountId = mc.account_id; m.user.platform = mc.platform; - std::strncpy(m.onlineId.data, mc.np_id.handle.data, sizeof(m.onlineId.data) - 1); + m.onlineId = mc.np_id.handle; m.roomGroup = p.room_groups.empty() ? nullptr : p.room_groups.data(); m.roomMemberInternalBinAttr = p.member_bin_attrs.empty() ? nullptr : p.member_bin_attrs.data(); @@ -350,7 +358,7 @@ void HandleRoomEvent(const ShadNet::NotifyRoomEvent& n) { mc.join_date = n.member_join_date; mc.addr = IpStringToAddr(n.member_addr); mc.port = Libraries::Net::sceNetHtons(static_cast(n.member_port)); - std::strncpy(mc.np_id.handle.data, n.member_npid.c_str(), sizeof(mc.np_id.handle.data) - 1); + SetNpId(mc.np_id, n.member_npid); mc.account_id = static_cast(n.member_account_id); mc.platform = static_cast(n.member_platform); for (const auto& a : n.member_bin_attrs) { @@ -363,7 +371,7 @@ void HandleRoomEvent(const ShadNet::NotifyRoomEvent& n) { pi.member_id = member_id; pi.addr = mc.addr; pi.port = mc.port; - std::strncpy(pi.online_id.data, n.member_npid.c_str(), sizeof(pi.online_id.data) - 1); + SetNpOnlineId(pi.online_id, n.member_npid); ctx->peers[member_id] = pi; BuildMemberUpdate(p, room_it->second, mc, cause, ctx->a_variant); @@ -657,11 +665,11 @@ void MmContextStart(OrbisNpMatching2ContextId ctx_id) { } } -void MmContextStop(OrbisNpMatching2ContextId ctx_id) { +s32 MmContextStop(OrbisNpMatching2ContextId ctx_id) { shadnet::ContextStopRequest req; req.set_ctx_id(ctx_id); - MmSubmitRequest(ctx_id, 0, ORBIS_NP_MATCHING2_CONTEXT_EVENT_STOPPED, MmCommand::ContextStop, - MakeProtoPayload(req)); + return MmSubmitRequest(ctx_id, 0, ORBIS_NP_MATCHING2_CONTEXT_EVENT_STOPPED, + MmCommand::ContextStop, MakeProtoPayload(req)); } s32 MmSubmitRequest(OrbisNpMatching2ContextId ctx_id, OrbisNpMatching2RequestId req_id, @@ -677,10 +685,24 @@ s32 MmSubmitRequest(OrbisNpMatching2ContextId ctx_id, OrbisNpMatching2RequestId return ORBIS_NP_MATCHING2_ERROR_INVALID_CONTEXT_ID; } + ContextObject* ctx = ContextManager::Instance().Get(ctx_id); + if (!ctx) { + LOG_ERROR(Lib_NpMatching2, "MmSubmitRequest({}): invalid ctx={}", static_cast(cmd), + ctx_id); + return ORBIS_NP_MATCHING2_ERROR_INVALID_CONTEXT_ID; + } + const RequestCallbackInfo request_cb = ConsumeRequestCallback(ctx); + LOG_INFO(Lib_NpMatching2, + "MmSubmitRequest: ctx={} reqId={} event={:#x} cmd={} aVariant={} callback={:#x} " + "arg={}", + ctx_id, req_id, static_cast(req_event), static_cast(cmd), a_variant, + reinterpret_cast(request_cb.callback), fmt::ptr(request_cb.arg)); + const u64 pkt_id = client->SubmitRequest(static_cast(cmd), payload); { std::lock_guard lock(g_mm.pending_mutex); - g_mm.pending[pkt_id] = {ctx_id, req_id, req_event, a_variant}; + g_mm.pending[pkt_id] = {ctx_id, req_id, req_event, a_variant, request_cb.callback, + request_cb.arg}; } LOG_DEBUG(Lib_NpMatching2, "submit cmd={} pkt_id={} ctx={} reqId={}", static_cast(cmd), pkt_id, ctx_id, req_id); diff --git a/src/core/libraries/np/np_matching2/np_matching2_mm.h b/src/core/libraries/np/np_matching2/np_matching2_mm.h index 685d120ba..10e6ebdab 100644 --- a/src/core/libraries/np/np_matching2/np_matching2_mm.h +++ b/src/core/libraries/np/np_matching2/np_matching2_mm.h @@ -45,7 +45,7 @@ void OnMatchingReply(ShadNet::CommandType cmd, u64 pkt_id, ShadNet::ErrorType er const std::vector& body); void MmContextStart(OrbisNpMatching2ContextId ctx_id); -void MmContextStop(OrbisNpMatching2ContextId ctx_id); +s32 MmContextStop(OrbisNpMatching2ContextId ctx_id); s32 MmSubmitRequest(OrbisNpMatching2ContextId ctx_id, OrbisNpMatching2RequestId req_id, OrbisNpMatching2Event req_event, MmCommand cmd, const std::vector& payload, diff --git a/src/core/libraries/np/np_matching2/np_matching2_signaling.cpp b/src/core/libraries/np/np_matching2/np_matching2_signaling.cpp index 306b03ce8..73cea0506 100644 --- a/src/core/libraries/np/np_matching2/np_matching2_signaling.cpp +++ b/src/core/libraries/np/np_matching2/np_matching2_signaling.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include "common/logging/log.h" @@ -102,8 +103,7 @@ bool ResolvePeerEndpoint(const MemberCache& member, PeerInfo& peer) { peer.addr = member.addr; peer.port = member.port; if (peer.online_id.data[0] == 0) { - std::strncpy(peer.online_id.data, member.np_id.handle.data, - sizeof(peer.online_id.data) - 1); + peer.online_id = member.np_id.handle; } return true; } @@ -116,8 +116,7 @@ bool ResolvePeerEndpoint(const MemberCache& member, PeerInfo& peer) { peer.port = resolved_port; } if (peer.online_id.data[0] == 0) { - std::strncpy(peer.online_id.data, member.np_id.handle.data, - sizeof(peer.online_id.data) - 1); + peer.online_id = member.np_id.handle; } return peer.addr != 0 && peer.port != 0; } @@ -238,7 +237,9 @@ void HandleMatching2HandshakePacket(u32 from_addr, u16 from_port, peer.status = peer.status == kMatching2ConnActive ? kMatching2ConnActive : kMatching2ConnPending; peer.handshake_started = true; - std::memcpy(peer.online_id.data, pkt.online_id_from, ORBIS_NP_ONLINEID_MAX_LENGTH); + SetNpOnlineId(peer.online_id, + std::string_view(reinterpret_cast(pkt.online_id_from), + ORBIS_NP_ONLINEID_MAX_LENGTH)); const auto kind = static_cast(pkt.kind); switch (kind) { @@ -485,7 +486,8 @@ u32 GetRoomPingUs(const ContextObject& ctx, OrbisNpMatching2RoomId roomId) { } void* BuildSignalingGetPingInfoPayload(ContextObject& ctx, OrbisNpMatching2RoomId roomId) { - CallbackPayload& p = ctx.request_payload; + CallbackPayload& p = + ctx.request_payload_override ? *ctx.request_payload_override : ctx.request_payload; p.Reset(); const auto room_it = ctx.room_cache.find(roomId); diff --git a/src/core/libraries/np/np_signaling/np_signaling_state.cpp b/src/core/libraries/np/np_signaling/np_signaling_state.cpp index 26cd9a2cd..96cbaf5e1 100644 --- a/src/core/libraries/np/np_signaling/np_signaling_state.cpp +++ b/src/core/libraries/np/np_signaling/np_signaling_state.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include "common/logging/log.h" #include "common/singleton.h" @@ -1228,7 +1229,9 @@ void HandleControlPacket(u32 from_addr, u16 from_port, const SignalingControl& p ci.conn_id = conn_id; ci.ctx_id = ctx_id; ci.locally_activated = false; - std::memcpy(ci.online_id.data, pkt.online_id_from, ORBIS_NP_ONLINEID_MAX_LENGTH); + SetNpOnlineId(ci.online_id, + std::string_view(reinterpret_cast(pkt.online_id_from), + ORBIS_NP_ONLINEID_MAX_LENGTH)); ci.npid.handle = ci.online_id; g_connections[conn_id] = std::move(ci); g_npid_to_conn[MakeCtxNpIdKey(ctx_id, g_connections[conn_id].npid)] = conn_id; diff --git a/src/core/libraries/np/np_types.h b/src/core/libraries/np/np_types.h index 26ad1316a..6fe5675f4 100644 --- a/src/core/libraries/np/np_types.h +++ b/src/core/libraries/np/np_types.h @@ -3,6 +3,10 @@ #pragma once +#include +#include +#include + #include "common/types.h" #include "core/libraries/error_codes.h" @@ -34,6 +38,20 @@ struct OrbisNpId { u8 reserved[8]; }; +inline void SetNpOnlineId(OrbisNpOnlineId& dst, std::string_view src) { + dst = {}; + const size_t len = std::min(src.size(), static_cast(ORBIS_NP_ONLINEID_MAX_LENGTH)); + if (len > 0) { + std::memcpy(dst.data, src.data(), len); + } + dst.term = 0; +} + +inline void SetNpId(OrbisNpId& dst, std::string_view online_id) { + dst = {}; + SetNpOnlineId(dst.handle, online_id); +} + struct OrbisNpClientId { char id[129]; u8 padding[7]; @@ -71,4 +89,4 @@ struct OrbisNpPeerAddressA { char padding[4]; }; -}; // namespace Libraries::Np \ No newline at end of file +}; // namespace Libraries::Np