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.
This commit is contained in:
metr1k-91 2026-07-06 15:49:29 -05:00 committed by GitHub
parent dd60483956
commit eabd04d35d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 182 additions and 63 deletions

View File

@ -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);

View File

@ -2,7 +2,9 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include <chrono>
#include <cstdint>
#include <cstring>
#include <memory>
#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<std::uintptr_t>(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<CallbackPayload>();
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;
}

View File

@ -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<u16>(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<Libraries::Np::OrbisNpAccountId>(m.account_id());
mc.platform = static_cast<Libraries::Np::OrbisNpPlatformType>(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<OrbisNpMatching2RoomMemberId>(m.member_id());
dst.teamId = static_cast<OrbisNpMatching2TeamId>(m.team_id());
dst.natType = static_cast<OrbisNpMatching2NatType>(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<Libraries::Np::OrbisNpAccountId>(m.account_id());
dst.user.platform = static_cast<Libraries::Np::OrbisNpPlatformType>(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<OrbisNpMatching2RoomMemberId>(m.member_id());
dst.teamId = static_cast<OrbisNpMatching2TeamId>(m.team_id());
dst.natType = static_cast<OrbisNpMatching2NatType>(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<OrbisNpMatching2LeaveRoomResponse>();
@ -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<u16>(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<Libraries::Np::OrbisNpAccountId>(r.owner_account_id());
dst.owner.platform = static_cast<Libraries::Np::OrbisNpPlatformType>(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<u16>(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<Libraries::Np::OrbisNpAccountId>(r.owner_account_id());
dst.owner.platform = static_cast<Libraries::Np::OrbisNpPlatformType>(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<OrbisNpMatching2Role>(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<Libraries::Np::OrbisNpAccountId>(src.account_id());
dst.user.platform = static_cast<Libraries::Np::OrbisNpPlatformType>(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<OrbisNpMatching2Role>(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<Libraries::Np::OrbisNpAccountId>(u.account_id());
dst.user.platform = static_cast<Libraries::Np::OrbisNpPlatformType>(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<u16>(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) {

View File

@ -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<OrbisNpMatching2RoomId, RoomCache> 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<CallbackPayload> 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);

View File

@ -3,6 +3,7 @@
#include <chrono>
#include <condition_variable>
#include <cstdint>
#include <cstring>
#include <map>
#include <memory>
@ -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<CallbackPayload> request_payload_owner;
if (error_code == 0) {
request_payload_owner = std::make_shared<CallbackPayload>();
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<u16>(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<Libraries::Np::OrbisNpAccountId>(n.member_account_id);
mc.platform = static_cast<Libraries::Np::OrbisNpPlatformType>(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<u16>(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<u16>(req_event), static_cast<u16>(cmd), a_variant,
reinterpret_cast<std::uintptr_t>(request_cb.callback), fmt::ptr(request_cb.arg));
const u64 pkt_id = client->SubmitRequest(static_cast<ShadNet::CommandType>(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<u16>(cmd),
pkt_id, ctx_id, req_id);

View File

@ -45,7 +45,7 @@ void OnMatchingReply(ShadNet::CommandType cmd, u64 pkt_id, ShadNet::ErrorType er
const std::vector<u8>& 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<u8>& payload,

View File

@ -9,6 +9,7 @@
#include <memory>
#include <mutex>
#include <string>
#include <string_view>
#include <thread>
#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<const char*>(pkt.online_id_from),
ORBIS_NP_ONLINEID_MAX_LENGTH));
const auto kind = static_cast<Matching2HandshakeKind>(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);

View File

@ -6,6 +6,7 @@
#include <cstring>
#include <mutex>
#include <random>
#include <string_view>
#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<const char*>(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;

View File

@ -3,6 +3,10 @@
#pragma once
#include <algorithm>
#include <cstring>
#include <string_view>
#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<size_t>(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
}; // namespace Libraries::Np