From 3e1f92353c5e394b4254c33d1c903e793c55390d Mon Sep 17 00:00:00 2001 From: metr1k-91 Date: Sun, 5 Jul 2026 00:00:16 -0500 Subject: [PATCH] matching2 - P7+P8: more public api additions, changes to context, corrections to multiple callback returns, corrections to A types, etc. (#4671) --- CMakeLists.txt | 2 +- src/core/libraries/np/np_handler.cpp | 2 +- .../np/np_matching2/np_matching2.cpp | 31 +- .../libraries/np/np_matching2/np_matching2.h | 137 +-- .../np/np_matching2/np_matching2_internal.cpp | 351 ++++++- .../np/np_matching2/np_matching2_internal.h | 36 +- .../np/np_matching2/np_matching2_mm.cpp | 150 ++- .../np/np_matching2/np_matching2_mm.h | 7 +- .../np_matching2/np_matching2_signaling.cpp | 14 + .../np/np_matching2/np_matching2_signaling.h | 1 + .../np/np_signaling/np_signaling.cpp | 33 +- .../libraries/np/np_signaling/np_signaling.h | 61 +- .../np/np_signaling/np_signaling_helpers.cpp | 3 +- .../np/np_signaling/np_signaling_state.cpp | 37 +- .../np/np_signaling/np_signaling_state.h | 4 +- .../np_matching2_types.h => np_types2.h} | 908 ++++++++++++------ src/shadnet/shadnet.proto | 11 + 17 files changed, 1217 insertions(+), 571 deletions(-) rename src/core/libraries/np/{np_matching2/np_matching2_types.h => np_types2.h} (60%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 93d6d7a54..5db114fa5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -638,7 +638,7 @@ set(NP_LIBS src/core/libraries/np/np_error.h src/core/libraries/np/np_matching2/np_matching2_mm.h src/core/libraries/np/np_matching2/np_matching2_signaling.cpp src/core/libraries/np/np_matching2/np_matching2_signaling.h - src/core/libraries/np/np_matching2/np_matching2_types.h + src/core/libraries/np/np_types2.h src/core/libraries/np/np_trophy.cpp src/core/libraries/np/np_trophy.h src/core/libraries/np/np_tus.cpp diff --git a/src/core/libraries/np/np_handler.cpp b/src/core/libraries/np/np_handler.cpp index c27e1f51a..6145ac56a 100644 --- a/src/core/libraries/np/np_handler.cpp +++ b/src/core/libraries/np/np_handler.cpp @@ -1626,7 +1626,7 @@ static u32 FillRankArrayFromProto(const shadnet::GetScoreResponse& resp, void NpHandler::OnAsyncReply(s32 user_id, ShadNet::CommandType cmd, u64 pkt_id, ShadNet::ErrorType error, const std::vector& body) { const auto cmd_val = static_cast(cmd); - if (cmd_val >= 12 && cmd_val <= 23) { + if (cmd_val >= 12 && cmd_val <= 24) { NpMatching2::OnMatchingReply(cmd, pkt_id, error, body); } else { OnScoreReply(user_id, cmd, pkt_id, error, body); diff --git a/src/core/libraries/np/np_matching2/np_matching2.cpp b/src/core/libraries/np/np_matching2/np_matching2.cpp index 4fd175ebe..c297b6aa5 100644 --- a/src/core/libraries/np/np_matching2/np_matching2.cpp +++ b/src/core/libraries/np/np_matching2/np_matching2.cpp @@ -15,7 +15,6 @@ #include "core/libraries/np/np_matching2/np_matching2_internal.h" #include "core/libraries/np/np_matching2/np_matching2_mm.h" #include "core/libraries/np/np_matching2/np_matching2_signaling.h" -#include "core/libraries/np/np_matching2/np_matching2_types.h" #include "core/libraries/np/np_types.h" #include "core/libraries/system/userservice.h" @@ -55,7 +54,7 @@ int PS4_SYSV_ABI sceNpMatching2CreateContextA(const OrbisNpMatching2CreateContex const Libraries::Np::OrbisNpId np_id = Libraries::Np::NpHandler::GetInstance().GetNpId(param->userId); - return ContextManager::Instance().CreateContext(&np_id, param->serviceLabel, ctxId); + return ContextManager::Instance().CreateContext(&np_id, param->serviceLabel, ctxId, true); } int PS4_SYSV_ABI sceNpMatching2CreateJoinRoom(OrbisNpMatching2ContextId ctxId, @@ -416,7 +415,7 @@ int PS4_SYSV_ABI sceNpMatching2SearchRoom(OrbisNpMatching2ContextId ctxId, StoreRequestCallback(ctx, requestOpt); const OrbisNpMatching2RequestId reqId = AllocRequestId(); *requestId = reqId; - MmSearchRoom(ctxId, reqId, *request); + MmSearchRoom(ctxId, reqId, *request, ctx->a_variant); return ORBIS_OK; } @@ -690,8 +689,30 @@ int PS4_SYSV_ABI sceNpMatching2GetLobbyMemberDataInternalList() { return ORBIS_OK; } -int PS4_SYSV_ABI sceNpMatching2GetRoomDataExternalList() { - LOG_INFO(Lib_NpMatching2, "called"); +int PS4_SYSV_ABI sceNpMatching2GetRoomDataExternalList( + OrbisNpMatching2ContextId ctxId, OrbisNpMatching2GetRoomDataExternalListRequest* request, + OrbisNpMatching2RequestOptParam* requestOpt, OrbisNpMatching2RequestId* requestId) { + LOG_INFO(Lib_NpMatching2, "called, ctxId = {}, requestOpt = {}", ctxId, fmt::ptr(requestOpt)); + + if (!IsInitialized()) { + LOG_ERROR(Lib_NpMatching2, "not initialized"); + return ORBIS_NP_MATCHING2_ERROR_NOT_INITIALIZED; + } + if (!request || !requestId) { + LOG_ERROR(Lib_NpMatching2, "request or requestId null"); + return ORBIS_NP_MATCHING2_ERROR_INVALID_ARGUMENT; + } + + ContextObject* ctx = ContextManager::Instance().Get(ctxId); + if (!ctx) { + LOG_ERROR(Lib_NpMatching2, "invalid context id"); + return ORBIS_NP_MATCHING2_ERROR_INVALID_CONTEXT_ID; + } + + StoreRequestCallback(ctx, requestOpt); + const OrbisNpMatching2RequestId reqId = AllocRequestId(); + *requestId = reqId; + MmGetRoomDataExternalList(ctxId, reqId, *request, ctx->a_variant); return ORBIS_OK; } diff --git a/src/core/libraries/np/np_matching2/np_matching2.h b/src/core/libraries/np/np_matching2/np_matching2.h index f12e584d1..c7c85e96a 100644 --- a/src/core/libraries/np/np_matching2/np_matching2.h +++ b/src/core/libraries/np/np_matching2/np_matching2.h @@ -4,6 +4,7 @@ #pragma once #include "common/types.h" +#include "core/libraries/np/np_types2.h" namespace Core::Loader { class SymbolsResolver; @@ -11,142 +12,6 @@ class SymbolsResolver; namespace Libraries::Np::NpMatching2 { -using OrbisNpMatching2AttributeId = u16; -using OrbisNpMatching2BlockKickFlag = u8; -using OrbisNpMatching2ContextId = u16; -using OrbisNpMatching2FlagAttr = u32; -using OrbisNpMatching2Flags = u32; -using OrbisNpMatching2LobbyId = u64; -using OrbisNpMatching2LobbyMemberId = u16; -using OrbisNpMatching2NatType = u8; -using OrbisNpMatching2RequestId = u32; -using OrbisNpMatching2RoomGroupId = u8; -using OrbisNpMatching2RoomId = u64; -using OrbisNpMatching2RoomMemberId = u16; -using OrbisNpMatching2RoomPasswordSlotMask = u64; -using OrbisNpMatching2ServerId = u16; -using OrbisNpMatching2SignalingFlag = u8; -using OrbisNpMatching2SignalingRequestId = u32; -using OrbisNpMatching2TeamId = u8; -using OrbisNpMatching2WorldId = u32; - -enum OrbisNpMatching2Event : u16 { - ORBIS_NP_MATCHING2_REQUEST_EVENT_GET_WORLD_INFO_LIST = 0x0002, - ORBIS_NP_MATCHING2_REQUEST_EVENT_SET_ROOM_DATA_EXTERNAL = 0x0004, - ORBIS_NP_MATCHING2_REQUEST_EVENT_SET_USER_INFO = 0x0007, - ORBIS_NP_MATCHING2_REQUEST_EVENT_CREATE_JOIN_ROOM = 0x0101, - ORBIS_NP_MATCHING2_REQUEST_EVENT_JOIN_ROOM = 0x0102, - ORBIS_NP_MATCHING2_REQUEST_EVENT_LEAVE_ROOM = 0x0103, - ORBIS_NP_MATCHING2_REQUEST_EVENT_KICKOUT_ROOM_MEMBER = 0x0104, - ORBIS_NP_MATCHING2_REQUEST_EVENT_GRANT_ROOM_OWNER = 0x0105, - ORBIS_NP_MATCHING2_REQUEST_EVENT_SEARCH_ROOM = 0x0106, - ORBIS_NP_MATCHING2_REQUEST_EVENT_SEND_ROOM_MESSAGE = 0x0108, - ORBIS_NP_MATCHING2_REQUEST_EVENT_SET_ROOM_DATA_INTERNAL = 0x0109, - ORBIS_NP_MATCHING2_REQUEST_EVENT_GET_ROOM_DATA_INTERNAL = 0x010A, - ORBIS_NP_MATCHING2_REQUEST_EVENT_JOIN_LOBBY = 0x0201, - ORBIS_NP_MATCHING2_REQUEST_EVENT_SIGNALING_GET_PING_INFO = 0x0E01, - ORBIS_NP_MATCHING2_ROOM_EVENT_MEMBER_JOINED = 0x1101, - ORBIS_NP_MATCHING2_ROOM_EVENT_MEMBER_LEFT = 0x1102, - ORBIS_NP_MATCHING2_ROOM_EVENT_KICKEDOUT = 0x1103, - ORBIS_NP_MATCHING2_ROOM_EVENT_ROOM_DESTROYED = 0x1104, - ORBIS_NP_MATCHING2_ROOM_EVENT_ROOM_OWNER_CHANGED = 0x1105, - ORBIS_NP_MATCHING2_ROOM_EVENT_UPDATED_ROOM_DATA_INTERNAL = 0x1106, - ORBIS_NP_MATCHING2_ROOM_EVENT_UPDATED_ROOM_MEMBER_DATA_INTERNAL = 0x1107, - ORBIS_NP_MATCHING2_ROOM_EVENT_UPDATED_SIGNALING_OPT_PARAM = 0x1108, - ORBIS_NP_MATCHING2_SIGNALING_EVENT_DEAD = 0x5101, - ORBIS_NP_MATCHING2_SIGNALING_EVENT_ESTABLISHED = 0x5102, - ORBIS_NP_MATCHING2_SIGNALING_EVENT_NETINFO_ERROR = 0x5103, - ORBIS_NP_MATCHING2_CONTEXT_EVENT_START_OVER = 0x6F01, - ORBIS_NP_MATCHING2_CONTEXT_EVENT_STARTED = 0x6F02, - ORBIS_NP_MATCHING2_CONTEXT_EVENT_STOPPED = 0x6F03, - ORBIS_NP_MATCHING2_REQUEST_EVENT_CREATE_JOIN_ROOM_A = 0x7101, - ORBIS_NP_MATCHING2_REQUEST_EVENT_JOIN_ROOM_A = 0x7102, - ORBIS_NP_MATCHING2_REQUEST_EVENT_SEARCH_ROOM_A = 0x7106, - ORBIS_NP_MATCHING2_ROOM_EVENT_MEMBER_JOINED_A = 0x8101, - ORBIS_NP_MATCHING2_ROOM_EVENT_MEMBER_LEFT_A = 0x8102, - ORBIS_NP_MATCHING2_ROOM_EVENT_UPDATED_ROOM_MEMBER_DATA_INTERNAL_A = 0x8107, - ORBIS_NP_MATCHING2_ROOM_MSG_EVENT_MESSAGE_A = 0x9102, -}; - -enum OrbisNpMatching2EventCause : u8 { - ORBIS_NP_MATCHING2_EVENT_CAUSE_LEAVE_ACTION = 1, - ORBIS_NP_MATCHING2_EVENT_CAUSE_KICKOUT_ACTION = 2, - ORBIS_NP_MATCHING2_EVENT_CAUSE_GRANT_OWNER_ACTION = 3, - ORBIS_NP_MATCHING2_EVENT_CAUSE_SERVER_OPERATION = 4, - ORBIS_NP_MATCHING2_EVENT_CAUSE_MEMBER_DISAPPEARED = 5, - ORBIS_NP_MATCHING2_EVENT_CAUSE_SERVER_INTERNAL = 6, - ORBIS_NP_MATCHING2_EVENT_CAUSE_CONNECTION_ERROR = 7, - ORBIS_NP_MATCHING2_EVENT_CAUSE_NP_SIGNED_OUT = 8, - ORBIS_NP_MATCHING2_EVENT_CAUSE_SYSTEM_ERROR = 9, - ORBIS_NP_MATCHING2_EVENT_CAUSE_CONTEXT_ERROR = 10, - ORBIS_NP_MATCHING2_EVENT_CAUSE_CONTEXT_ACTION = 11, -}; - -enum OrbisNpMatching2SignalingType : u8 { - ORBIS_NP_MATCHING2_SIGNALING_TYPE_NONE = 0, - ORBIS_NP_MATCHING2_SIGNALING_TYPE_MESH = 1, - ORBIS_NP_MATCHING2_SIGNALING_TYPE_STAR = 2, -}; - -enum OrbisNpMatching2SignalingConnectionInfoType : s32 { - ORBIS_NP_MATCHING2_SIGNALING_CONN_INFO_RTT = 1, - ORBIS_NP_MATCHING2_SIGNALING_CONN_INFO_BANDWIDTH = 2, - ORBIS_NP_MATCHING2_SIGNALING_CONN_INFO_PEER_NP_ID = 3, - ORBIS_NP_MATCHING2_SIGNALING_CONN_INFO_PEER_ADDR = 4, - ORBIS_NP_MATCHING2_SIGNALING_CONN_INFO_MAPPED_ADDR = 5, - ORBIS_NP_MATCHING2_SIGNALING_CONN_INFO_PACKET_LOSS = 6, - ORBIS_NP_MATCHING2_SIGNALING_CONN_INFO_PEER_NPID = 7, - ORBIS_NP_MATCHING2_SIGNALING_CONN_INFO_PEER_ADDRESS_A = 7, -}; - -enum OrbisNpMatching2AttrId : OrbisNpMatching2AttributeId { - ORBIS_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_1_ID = 0x004C, - ORBIS_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_2_ID = 0x004D, - ORBIS_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_3_ID = 0x004E, - ORBIS_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_4_ID = 0x004F, - ORBIS_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_5_ID = 0x0050, - ORBIS_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_6_ID = 0x0051, - ORBIS_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_7_ID = 0x0052, - ORBIS_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_8_ID = 0x0053, - ORBIS_NP_MATCHING2_ROOM_SEARCHABLE_BIN_ATTR_EXTERNAL_1_ID = 0x0054, - ORBIS_NP_MATCHING2_ROOM_BIN_ATTR_EXTERNAL_1_ID = 0x0055, - ORBIS_NP_MATCHING2_ROOM_BIN_ATTR_EXTERNAL_2_ID = 0x0056, - ORBIS_NP_MATCHING2_ROOM_BIN_ATTR_INTERNAL_1_ID = 0x0057, - ORBIS_NP_MATCHING2_ROOM_BIN_ATTR_INTERNAL_2_ID = 0x0058, - ORBIS_NP_MATCHING2_ROOMMEMBER_BIN_ATTR_INTERNAL_1_ID = 0x0059, -}; - -enum OrbisNpMatching2RoomFlagAttr : OrbisNpMatching2Flags { - ORBIS_NP_MATCHING2_ROOM_FLAG_ATTR_OWNER_AUTO_GRANT = 0x80000000, - ORBIS_NP_MATCHING2_ROOM_FLAG_ATTR_CLOSED = 0x40000000, - ORBIS_NP_MATCHING2_ROOM_FLAG_ATTR_FULL = 0x20000000, - ORBIS_NP_MATCHING2_ROOM_FLAG_ATTR_HIDDEN = 0x10000000, - ORBIS_NP_MATCHING2_ROOM_FLAG_ATTR_NAT_TYPE_RESTRICTION = 0x04000000, - ORBIS_NP_MATCHING2_ROOM_FLAG_ATTR_PROHIBITIVE_MODE = 0x02000000, -}; - -enum OrbisNpMatching2RoomMemberFlagAttr : OrbisNpMatching2Flags { - ORBIS_NP_MATCHING2_ROOMMEMBER_FLAG_ATTR_OWNER = 0x80000000, -}; - -enum OrbisNpMatching2Role : u8 { - ORBIS_NP_MATCHING2_ROLE_MEMBER = 1, - ORBIS_NP_MATCHING2_ROLE_OWNER = 2, -}; - -constexpr u32 ORBIS_NP_MATCHING2_SESSION_PASSWORD_SIZE = 8; -constexpr u32 ORBIS_NP_MATCHING2_GROUP_LABEL_SIZE = 8; - -enum OrbisNpMatching2InitDefault : u64 { - ORBIS_NP_MATCHING2_THREAD_STACK_SIZE_DEFAULT = 32768, - ORBIS_NP_MATCHING2_POOLSIZE_DEFAULT = 131072, - ORBIS_NP_MATCHING2_SSL_POOLSIZE_DEFAULT = 196608, -}; - -struct OrbisNpMatching2InitializeParameter; -struct OrbisNpMatching2CreateContextParameter; -struct OrbisNpMatching2CreateContextParameterA; - int PS4_SYSV_ABI sceNpMatching2Initialize(OrbisNpMatching2InitializeParameter* param); int PS4_SYSV_ABI sceNpMatching2Terminate(); int PS4_SYSV_ABI sceNpMatching2CreateContext(const OrbisNpMatching2CreateContextParameter* param, 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 b702e3112..b462abe4d 100644 --- a/src/core/libraries/np/np_matching2/np_matching2_internal.cpp +++ b/src/core/libraries/np/np_matching2/np_matching2_internal.cpp @@ -28,6 +28,34 @@ u32 IpStringToAddr(std::string_view ip) { return a | (b << 8) | (c << 16) | (d << 24); } +template +void ReserveExternalRoomPayloadStorage(CallbackPayload& p, const Reply& resp) { + size_t groups = 0; + size_t int_attrs = 0; + size_t bin_attrs = 0; + size_t bin_buffers = 0; + size_t owners = 0; + + for (int i = 0; i < resp.rooms_size(); ++i) { + const auto& r = resp.rooms(i); + groups += static_cast(r.groups_size()); + int_attrs += static_cast(r.external_search_int_attrs_size()); + const size_t room_bin_attrs = static_cast(r.external_search_bin_attrs_size()) + + static_cast(r.external_bin_attrs_size()); + bin_attrs += room_bin_attrs; + bin_buffers += room_bin_attrs; + if (!r.owner_npid().empty()) { + ++owners; + } + } + + p.ext_room_groups.reserve(groups); + p.ext_int_attrs.reserve(int_attrs); + p.ext_bin_attrs.reserve(bin_attrs); + p.bin_buffers.reserve(bin_buffers); + p.ext_owner_npids.reserve(owners); +} + } // namespace void BuildCreateJoinRoomPayloadCommon(ContextObject& ctx, @@ -343,6 +371,7 @@ void* BuildGetWorldInfoListPayload(ContextObject& ctx, const shadnet::GetWorldIn void* BuildSearchRoomPayload(ContextObject& ctx, const shadnet::SearchRoomReply& resp) { CallbackPayload& p = ctx.request_payload; p.Reset(); + ReserveExternalRoomPayloadStorage(p, resp); const int room_count = resp.rooms_size(); p.room_data_external.resize(room_count); @@ -444,6 +473,321 @@ void* BuildSearchRoomPayload(ContextObject& ctx, const shadnet::SearchRoomReply& return p.request_data; } +void* BuildSearchRoomPayloadA(ContextObject& ctx, const shadnet::SearchRoomReply& resp) { + CallbackPayload& p = ctx.request_payload; + p.Reset(); + ReserveExternalRoomPayloadStorage(p, resp); + + const int room_count = resp.rooms_size(); + p.room_data_external_a.resize(room_count); + for (int i = 0; i < room_count; ++i) { + const auto& r = resp.rooms(i); + auto& dst = p.room_data_external_a[i]; + dst = OrbisNpMatching2RoomDataExternalA{}; + dst.next = (i + 1 < room_count) ? &p.room_data_external_a[i + 1] : nullptr; + dst.maxSlot = static_cast(r.max_slot()); + dst.curMembers = static_cast(r.cur_members()); + dst.flags = r.flags(); + dst.serverId = static_cast(r.server_id()); + dst.worldId = static_cast(r.world_id()); + dst.lobbyId = r.lobby_id(); + dst.roomId = r.room_id(); + dst.passwdSlotMask = r.passwd_slot_mask(); + dst.joinedSlotMask = r.joined_slot_mask(); + dst.publicSlots = static_cast(r.public_slots()); + dst.privateSlots = static_cast(r.private_slots()); + dst.openPublicSlots = static_cast(r.open_public_slots()); + 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); + } + dst.owner.accountId = static_cast(r.owner_account_id()); + dst.owner.platform = static_cast(r.owner_platform()); + + if (r.groups_size() > 0) { + OrbisNpMatching2RoomGroupInfo* first = nullptr; + for (int g = 0; g < r.groups_size(); ++g) { + const auto& src = r.groups(g); + auto& gi = p.ext_room_groups.emplace_back(); + gi = OrbisNpMatching2RoomGroupInfo{}; + gi.id = static_cast(src.group_id()); + gi.hasPasswd = src.has_passwd(); + gi.slots = src.slot_count(); + gi.groupMembers = src.num_members(); + if (!first) { + first = &gi; + } + } + dst.roomGroup = first; + dst.roomGroups = static_cast(r.groups_size()); + } + + if (r.external_search_int_attrs_size() > 0) { + OrbisNpMatching2IntAttr* first = nullptr; + for (int a = 0; a < r.external_search_int_attrs_size(); ++a) { + const auto& src = r.external_search_int_attrs(a); + auto& ia = p.ext_int_attrs.emplace_back(); + ia = OrbisNpMatching2IntAttr{}; + ia.id = static_cast(src.attr_id()); + ia.num = src.attr_value(); + if (!first) { + first = &ia; + } + } + dst.externalSearchIntAttr = first; + dst.externalSearchIntAttrs = static_cast(r.external_search_int_attrs_size()); + } + + auto build_bin = [&](const auto& src_attrs, OrbisNpMatching2BinAttr*& out_ptr, + u64& out_num) { + if (src_attrs.empty()) { + return; + } + OrbisNpMatching2BinAttr* first = nullptr; + for (const auto& src : src_attrs) { + p.bin_buffers.emplace_back(src.data().begin(), src.data().end()); + auto& buf = p.bin_buffers.back(); + auto& ba = p.ext_bin_attrs.emplace_back(); + ba = OrbisNpMatching2BinAttr{}; + ba.id = static_cast(src.attr_id()); + ba.data = buf.empty() ? nullptr : buf.data(); + ba.dataSize = buf.size(); + if (!first) { + first = &ba; + } + } + out_ptr = first; + out_num = static_cast(src_attrs.size()); + }; + build_bin(r.external_search_bin_attrs(), dst.externalSearchBinAttr, + dst.externalSearchBinAttrs); + build_bin(r.external_bin_attrs(), dst.externalBinAttr, dst.externalBinAttrs); + } + + p.search_room_response_a = std::make_unique(); + auto& out = *p.search_room_response_a; + out = OrbisNpMatching2SearchRoomResponseA{}; + out.range.start = resp.range_start(); + out.range.total = resp.range_total(); + out.range.results = resp.range_result(); + out.roomDataExt = p.room_data_external_a.empty() ? nullptr : p.room_data_external_a.data(); + + p.request_data = p.search_room_response_a.get(); + return p.request_data; +} + +void* BuildGetRoomDataExternalListPayload(ContextObject& ctx, + const shadnet::GetRoomDataExternalListReply& resp) { + CallbackPayload& p = ctx.request_payload; + p.Reset(); + ReserveExternalRoomPayloadStorage(p, resp); + + const int room_count = resp.rooms_size(); + p.room_data_external.resize(room_count); + for (int i = 0; i < room_count; ++i) { + const auto& r = resp.rooms(i); + auto& dst = p.room_data_external[i]; + dst = OrbisNpMatching2RoomDataExternal{}; + dst.next = (i + 1 < room_count) ? &p.room_data_external[i + 1] : nullptr; + dst.maxSlot = static_cast(r.max_slot()); + dst.curMembers = static_cast(r.cur_members()); + dst.flags = r.flags(); + dst.serverId = static_cast(r.server_id()); + dst.worldId = static_cast(r.world_id()); + dst.lobbyId = r.lobby_id(); + dst.roomId = r.room_id(); + dst.passwdSlotMask = r.passwd_slot_mask(); + dst.joinedSlotMask = r.joined_slot_mask(); + dst.publicSlots = static_cast(r.public_slots()); + dst.privateSlots = static_cast(r.private_slots()); + dst.openPublicSlots = static_cast(r.open_public_slots()); + dst.openPrivateSlots = static_cast(r.open_private_slots()); + + 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); + dst.ownerNpId = &npid; + } + + if (r.groups_size() > 0) { + OrbisNpMatching2RoomGroupInfo* first = nullptr; + for (int g = 0; g < r.groups_size(); ++g) { + const auto& src = r.groups(g); + auto& gi = p.ext_room_groups.emplace_back(); + gi = OrbisNpMatching2RoomGroupInfo{}; + gi.id = static_cast(src.group_id()); + gi.hasPasswd = src.has_passwd(); + gi.slots = src.slot_count(); + gi.groupMembers = src.num_members(); + if (!first) { + first = &gi; + } + } + dst.roomGroup = first; + dst.roomGroups = static_cast(r.groups_size()); + } + + if (r.external_search_int_attrs_size() > 0) { + OrbisNpMatching2IntAttr* first = nullptr; + for (int a = 0; a < r.external_search_int_attrs_size(); ++a) { + const auto& src = r.external_search_int_attrs(a); + auto& ia = p.ext_int_attrs.emplace_back(); + ia = OrbisNpMatching2IntAttr{}; + ia.id = static_cast(src.attr_id()); + ia.num = src.attr_value(); + if (!first) { + first = &ia; + } + } + dst.externalSearchIntAttr = first; + dst.externalSearchIntAttrs = static_cast(r.external_search_int_attrs_size()); + } + + auto build_bin = [&](const auto& src_attrs, OrbisNpMatching2BinAttr*& out_ptr, + u64& out_num) { + if (src_attrs.empty()) { + return; + } + OrbisNpMatching2BinAttr* first = nullptr; + for (const auto& src : src_attrs) { + p.bin_buffers.emplace_back(src.data().begin(), src.data().end()); + auto& buf = p.bin_buffers.back(); + auto& ba = p.ext_bin_attrs.emplace_back(); + ba = OrbisNpMatching2BinAttr{}; + ba.id = static_cast(src.attr_id()); + ba.data = buf.empty() ? nullptr : buf.data(); + ba.dataSize = buf.size(); + if (!first) { + first = &ba; + } + } + out_ptr = first; + out_num = static_cast(src_attrs.size()); + }; + build_bin(r.external_search_bin_attrs(), dst.externalSearchBinAttr, + dst.externalSearchBinAttrs); + build_bin(r.external_bin_attrs(), dst.externalBinAttr, dst.externalBinAttrs); + } + + p.room_data_external_list_response = + std::make_unique(); + auto& out = *p.room_data_external_list_response; + out = OrbisNpMatching2GetRoomDataExternalListResponse{}; + out.roomDataExternal = p.room_data_external.empty() ? nullptr : p.room_data_external.data(); + out.roomDataExternalNum = static_cast(p.room_data_external.size()); + + p.request_data = p.room_data_external_list_response.get(); + return p.request_data; +} + +void* BuildGetRoomDataExternalListPayloadA(ContextObject& ctx, + const shadnet::GetRoomDataExternalListReply& resp) { + CallbackPayload& p = ctx.request_payload; + p.Reset(); + ReserveExternalRoomPayloadStorage(p, resp); + + const int room_count = resp.rooms_size(); + p.room_data_external_a.resize(room_count); + for (int i = 0; i < room_count; ++i) { + const auto& r = resp.rooms(i); + auto& dst = p.room_data_external_a[i]; + dst = OrbisNpMatching2RoomDataExternalA{}; + dst.next = (i + 1 < room_count) ? &p.room_data_external_a[i + 1] : nullptr; + dst.maxSlot = static_cast(r.max_slot()); + dst.curMembers = static_cast(r.cur_members()); + dst.flags = r.flags(); + dst.serverId = static_cast(r.server_id()); + dst.worldId = static_cast(r.world_id()); + dst.lobbyId = r.lobby_id(); + dst.roomId = r.room_id(); + dst.passwdSlotMask = r.passwd_slot_mask(); + dst.joinedSlotMask = r.joined_slot_mask(); + dst.publicSlots = static_cast(r.public_slots()); + dst.privateSlots = static_cast(r.private_slots()); + dst.openPublicSlots = static_cast(r.open_public_slots()); + 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); + } + dst.owner.accountId = static_cast(r.owner_account_id()); + dst.owner.platform = static_cast(r.owner_platform()); + + if (r.groups_size() > 0) { + OrbisNpMatching2RoomGroupInfo* first = nullptr; + for (int g = 0; g < r.groups_size(); ++g) { + const auto& src = r.groups(g); + auto& gi = p.ext_room_groups.emplace_back(); + gi = OrbisNpMatching2RoomGroupInfo{}; + gi.id = static_cast(src.group_id()); + gi.hasPasswd = src.has_passwd(); + gi.slots = src.slot_count(); + gi.groupMembers = src.num_members(); + if (!first) { + first = &gi; + } + } + dst.roomGroup = first; + dst.roomGroups = static_cast(r.groups_size()); + } + + if (r.external_search_int_attrs_size() > 0) { + OrbisNpMatching2IntAttr* first = nullptr; + for (int a = 0; a < r.external_search_int_attrs_size(); ++a) { + const auto& src = r.external_search_int_attrs(a); + auto& ia = p.ext_int_attrs.emplace_back(); + ia = OrbisNpMatching2IntAttr{}; + ia.id = static_cast(src.attr_id()); + ia.num = src.attr_value(); + if (!first) { + first = &ia; + } + } + dst.externalSearchIntAttr = first; + dst.externalSearchIntAttrs = static_cast(r.external_search_int_attrs_size()); + } + + auto build_bin = [&](const auto& src_attrs, OrbisNpMatching2BinAttr*& out_ptr, + u64& out_num) { + if (src_attrs.empty()) { + return; + } + OrbisNpMatching2BinAttr* first = nullptr; + for (const auto& src : src_attrs) { + p.bin_buffers.emplace_back(src.data().begin(), src.data().end()); + auto& buf = p.bin_buffers.back(); + auto& ba = p.ext_bin_attrs.emplace_back(); + ba = OrbisNpMatching2BinAttr{}; + ba.id = static_cast(src.attr_id()); + ba.data = buf.empty() ? nullptr : buf.data(); + ba.dataSize = buf.size(); + if (!first) { + first = &ba; + } + } + out_ptr = first; + out_num = static_cast(src_attrs.size()); + }; + build_bin(r.external_search_bin_attrs(), dst.externalSearchBinAttr, + dst.externalSearchBinAttrs); + build_bin(r.external_bin_attrs(), dst.externalBinAttr, dst.externalBinAttrs); + } + + p.room_data_external_list_response_a = + std::make_unique(); + auto& out = *p.room_data_external_list_response_a; + out = OrbisNpMatching2GetRoomDataExternalListResponseA{}; + out.roomDataExternal = p.room_data_external_a.empty() ? nullptr : p.room_data_external_a.data(); + out.roomDataExternalNum = static_cast(p.room_data_external_a.size()); + + p.request_data = p.room_data_external_list_response_a.get(); + return p.request_data; +} + void* BuildGetRoomDataInternalPayload(ContextObject& ctx, OrbisNpMatching2RoomId room_id) { const auto rc_it = ctx.room_cache.find(room_id); if (rc_it == ctx.room_cache.end()) { @@ -548,7 +892,7 @@ ContextObject* ContextManager::GetLocked(OrbisNpMatching2ContextId ctx_id) { } s32 ContextManager::CreateContext(const OrbisNpId* owner_np_id, OrbisNpServiceLabel service_label, - OrbisNpMatching2ContextId* out_ctx_id) { + OrbisNpMatching2ContextId* out_ctx_id, bool a_variant) { if (!out_ctx_id) { return ORBIS_NP_MATCHING2_ERROR_INVALID_ARGUMENT; } @@ -572,6 +916,7 @@ s32 ContextManager::CreateContext(const OrbisNpId* owner_np_id, OrbisNpServiceLa ContextObject& ctx = m_contexts[id]; ctx.Reset(); ctx.ctx_id = id; + ctx.a_variant = a_variant; ctx.service_label = service_label; if (owner_np_id) { ctx.owner_np_id = *owner_np_id; @@ -582,8 +927,8 @@ s32 ContextManager::CreateContext(const OrbisNpId* owner_np_id, OrbisNpServiceLa m_used[id] = true; *out_ctx_id = id; - LOG_DEBUG(Lib_NpMatching2, "context created: id={} online_id={} serviceLabel={:#x}", id, - ctx.online_id.data, service_label); + LOG_DEBUG(Lib_NpMatching2, "context{} created: id={} online_id={} serviceLabel={:#x}", + a_variant ? "A" : "", id, ctx.online_id.data, service_label); return ORBIS_OK; } 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 ede416c3f..e79eec2ed 100644 --- a/src/core/libraries/np/np_matching2/np_matching2_internal.h +++ b/src/core/libraries/np/np_matching2/np_matching2_internal.h @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include @@ -17,12 +16,12 @@ #include "common/types.h" #include "core/libraries/kernel/threads.h" #include "core/libraries/np/np_matching2/np_matching2.h" -#include "core/libraries/np/np_matching2/np_matching2_types.h" #include "core/libraries/np/np_types.h" namespace shadnet { class CreateJoinRoomResponse; class GetWorldInfoListReply; +class GetRoomDataExternalListReply; class LeaveRoomReply; class SearchRoomReply; } // namespace shadnet @@ -96,6 +95,11 @@ struct CallbackPayload { std::unique_ptr create_join_response_a; std::unique_ptr leave_room_response; std::unique_ptr search_room_response; + std::unique_ptr search_room_response_a; + std::unique_ptr + room_data_external_list_response; + std::unique_ptr + room_data_external_list_response_a; std::unique_ptr world_info_response; std::unique_ptr ping_info_response; std::vector world_list; @@ -107,14 +111,16 @@ struct CallbackPayload { std::vector room_bin_attr_ptrs; std::vector member_bin_attrs; std::vector room_data_external; + std::vector room_data_external_a; std::vector> bin_buffers; - std::deque ext_int_attrs; - std::deque ext_bin_attrs; - std::deque ext_room_groups; - std::deque ext_owner_npids; + std::vector ext_int_attrs; + std::vector ext_bin_attrs; + std::vector ext_room_groups; + std::vector ext_owner_npids; void* request_data = nullptr; std::unique_ptr room_member_update; + std::unique_ptr room_member_update_a; std::unique_ptr room_update; std::unique_ptr room_data_internal_update; std::unique_ptr event_chg_flag_attr; @@ -122,6 +128,7 @@ struct CallbackPayload { std::unique_ptr event_chg_passwd_slot_mask; std::unique_ptr event_prev_passwd_slot_mask; std::unique_ptr event_member; + std::unique_ptr event_member_a; void* room_event_data = nullptr; CallbackPayload() = default; @@ -136,6 +143,9 @@ struct CallbackPayload { create_join_response_a.reset(); leave_room_response.reset(); search_room_response.reset(); + search_room_response_a.reset(); + room_data_external_list_response.reset(); + room_data_external_list_response_a.reset(); world_info_response.reset(); ping_info_response.reset(); world_list.clear(); @@ -147,6 +157,7 @@ struct CallbackPayload { room_bin_attr_ptrs.clear(); member_bin_attrs.clear(); room_data_external.clear(); + room_data_external_a.clear(); bin_buffers.clear(); ext_int_attrs.clear(); ext_bin_attrs.clear(); @@ -154,6 +165,7 @@ struct CallbackPayload { ext_owner_npids.clear(); request_data = nullptr; room_member_update.reset(); + room_member_update_a.reset(); room_update.reset(); room_data_internal_update.reset(); event_chg_flag_attr.reset(); @@ -161,6 +173,7 @@ struct CallbackPayload { event_chg_passwd_slot_mask.reset(); event_prev_passwd_slot_mask.reset(); event_member.reset(); + event_member_a.reset(); room_event_data = nullptr; } }; @@ -168,6 +181,7 @@ struct CallbackPayload { struct ContextObject { OrbisNpMatching2ContextId ctx_id = 0; bool started = false; + bool a_variant = false; OrbisNpMatching2ServerId server_id = 1; OrbisNpServiceLabel service_label = 0; @@ -214,6 +228,7 @@ struct ContextObject { void Reset() { ctx_id = 0; started = false; + a_variant = false; server_id = 1; service_label = 0; owner_np_id = {}; @@ -253,12 +268,12 @@ struct ContextObject { class ContextManager { public: - static constexpr u32 kMaxContexts = 255; + static constexpr u32 kMaxContexts = 10; static ContextManager& Instance(); s32 CreateContext(const OrbisNpId* owner_np_id, OrbisNpServiceLabel service_label, - OrbisNpMatching2ContextId* out_ctx_id); + OrbisNpMatching2ContextId* out_ctx_id, bool a_variant = false); bool Check(OrbisNpMatching2ContextId ctx_id); ContextObject* Get(OrbisNpMatching2ContextId ctx_id); @@ -351,6 +366,11 @@ void* BuildCreateJoinRoomPayloadA(ContextObject& ctx, const shadnet::CreateJoinR void* BuildLeaveRoomPayload(ContextObject& ctx, const shadnet::LeaveRoomReply& resp); void* BuildGetWorldInfoListPayload(ContextObject& ctx, const shadnet::GetWorldInfoListReply& resp); void* BuildSearchRoomPayload(ContextObject& ctx, const shadnet::SearchRoomReply& resp); +void* BuildSearchRoomPayloadA(ContextObject& ctx, const shadnet::SearchRoomReply& resp); +void* BuildGetRoomDataExternalListPayload(ContextObject& ctx, + const shadnet::GetRoomDataExternalListReply& resp); +void* BuildGetRoomDataExternalListPayloadA(ContextObject& ctx, + const shadnet::GetRoomDataExternalListReply& resp); void* BuildGetRoomDataInternalPayload(ContextObject& ctx, OrbisNpMatching2RoomId room_id); void InitEventDispatcher(); 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 5fa0c4c22..9658a7b3c 100644 --- a/src/core/libraries/np/np_matching2/np_matching2_mm.cpp +++ b/src/core/libraries/np/np_matching2/np_matching2_mm.cpp @@ -190,10 +190,19 @@ void DispatchRequestComplete(const PendingRequest& pr, ShadNet::ErrorType error, if (reply.ParseFromString(proto)) { request_data = BuildGetWorldInfoListPayload(*ctx, reply); } - } else if (pr.req_event == ORBIS_NP_MATCHING2_REQUEST_EVENT_SEARCH_ROOM) { + } else if (pr.req_event == ORBIS_NP_MATCHING2_REQUEST_EVENT_SEARCH_ROOM || + pr.req_event == ORBIS_NP_MATCHING2_REQUEST_EVENT_SEARCH_ROOM_A) { shadnet::SearchRoomReply reply; if (reply.ParseFromString(proto)) { - request_data = BuildSearchRoomPayload(*ctx, reply); + request_data = pr.a_variant ? BuildSearchRoomPayloadA(*ctx, reply) + : BuildSearchRoomPayload(*ctx, reply); + } + } else if (pr.req_event == ORBIS_NP_MATCHING2_REQUEST_EVENT_GET_ROOM_DATA_EXTERNAL_LIST || + pr.req_event == ORBIS_NP_MATCHING2_REQUEST_EVENT_GET_ROOM_DATA_EXTERNAL_LIST_A) { + shadnet::GetRoomDataExternalListReply reply; + if (reply.ParseFromString(proto)) { + request_data = pr.a_variant ? BuildGetRoomDataExternalListPayloadA(*ctx, reply) + : BuildGetRoomDataExternalListPayload(*ctx, reply); } } } @@ -210,16 +219,71 @@ void DispatchRequestComplete(const PendingRequest& pr, ShadNet::ErrorType error, ev.request_data = request_data; ScheduleEvent(std::move(ev)); - if (error_code == 0 && (pr.req_event == ORBIS_NP_MATCHING2_REQUEST_EVENT_CREATE_JOIN_ROOM || - pr.req_event == ORBIS_NP_MATCHING2_REQUEST_EVENT_CREATE_JOIN_ROOM_A || - pr.req_event == ORBIS_NP_MATCHING2_REQUEST_EVENT_JOIN_ROOM || + if (error_code == 0 && (pr.req_event == ORBIS_NP_MATCHING2_REQUEST_EVENT_JOIN_ROOM || pr.req_event == ORBIS_NP_MATCHING2_REQUEST_EVENT_JOIN_ROOM_A)) { StartMatching2SignalingForRoomPeers(*ctx, ctx->room_id); + QueueMatching2EstablishedForRoomPeers(*ctx, ctx->room_id); + } else if (error_code == 0 && + (pr.req_event == ORBIS_NP_MATCHING2_REQUEST_EVENT_CREATE_JOIN_ROOM || + pr.req_event == ORBIS_NP_MATCHING2_REQUEST_EVENT_CREATE_JOIN_ROOM_A)) { + StartMatching2SignalingForRoomPeers(*ctx, ctx->room_id); + } +} + +void AppendEventMemberBinAttrs(CallbackPayload& p, const MemberCache& mc) { + p.member_bin_attrs.resize(mc.bins.size()); + p.bin_buffers.reserve(mc.bins.size()); + size_t i = 0; + for (const auto& [attr_id, bin] : mc.bins) { + p.bin_buffers.emplace_back(bin.data.begin(), bin.data.end()); + auto& buf = p.bin_buffers.back(); + auto& dst = p.member_bin_attrs[i++]; + dst = OrbisNpMatching2RoomMemberBinAttrInternal{}; + dst.lastUpdate.tick = bin.update_date; + dst.binAttr.id = bin.id; + dst.binAttr.data = buf.empty() ? nullptr : buf.data(); + dst.binAttr.dataSize = buf.size(); } } void BuildMemberUpdate(CallbackPayload& p, const RoomCache& rc, const MemberCache& mc, - OrbisNpMatching2EventCause cause) { + OrbisNpMatching2EventCause cause, bool a_variant) { + if (mc.group_id != 0) { + auto grp_it = rc.groups.find(mc.group_id); + if (grp_it != rc.groups.end()) { + p.room_groups.resize(1); + p.room_groups[0] = grp_it->second; + } + } + + AppendEventMemberBinAttrs(p, mc); + + if (a_variant) { + p.event_member_a = std::make_unique(); + OrbisNpMatching2RoomMemberDataInternalA& m = *p.event_member_a; + m = OrbisNpMatching2RoomMemberDataInternalA{}; + m.memberId = mc.member_id; + m.teamId = mc.team_id; + m.natType = mc.nat_type; + m.flags = mc.flag_attr; + 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.roomGroup = p.room_groups.empty() ? nullptr : p.room_groups.data(); + m.roomMemberInternalBinAttr = + p.member_bin_attrs.empty() ? nullptr : p.member_bin_attrs.data(); + m.roomMemberInternalBinAttrs = p.member_bin_attrs.size(); + + p.room_member_update_a = std::make_unique(); + OrbisNpMatching2RoomMemberUpdateA& u = *p.room_member_update_a; + u = OrbisNpMatching2RoomMemberUpdateA{}; + u.roomMemberDataInternal = p.event_member_a.get(); + u.eventCause = cause; + p.room_event_data = p.room_member_update_a.get(); + return; + } + p.event_member = std::make_unique(); OrbisNpMatching2RoomMemberDataInternal& m = *p.event_member; m = OrbisNpMatching2RoomMemberDataInternal{}; @@ -229,28 +293,7 @@ void BuildMemberUpdate(CallbackPayload& p, const RoomCache& rc, const MemberCach m.flagAttr = mc.flag_attr; m.joinDate = mc.join_date; m.npId = mc.np_id; - - if (mc.group_id != 0) { - auto grp_it = rc.groups.find(mc.group_id); - if (grp_it != rc.groups.end()) { - p.room_groups.resize(1); - p.room_groups[0] = grp_it->second; - m.roomGroup = p.room_groups.data(); - } - } - - p.member_bin_attrs.resize(mc.bins.size()); - p.bin_buffers.reserve(mc.bins.size()); - size_t i = 0; - for (const auto& [attr_id, bin] : mc.bins) { - p.bin_buffers.emplace_back(bin.data.begin(), bin.data.end()); - auto& buf = p.bin_buffers.back(); - auto& dst = p.member_bin_attrs[i++]; - dst = OrbisNpMatching2RoomMemberBinAttrInternal{}; - dst.binAttr.id = bin.id; - dst.binAttr.data = buf.empty() ? nullptr : buf.data(); - dst.binAttr.dataSize = buf.size(); - } + m.roomGroup = p.room_groups.empty() ? nullptr : p.room_groups.data(); m.roomMemberBinAttrInternal = p.member_bin_attrs.empty() ? nullptr : p.member_bin_attrs.data(); m.roomMemberBinAttrInternalNum = p.member_bin_attrs.size(); @@ -308,7 +351,7 @@ void HandleRoomEvent(const ShadNet::NotifyRoomEvent& n) { std::strncpy(pi.online_id.data, n.member_npid.c_str(), sizeof(pi.online_id.data) - 1); ctx->peers[member_id] = pi; - BuildMemberUpdate(p, room_it->second, mc, cause); + BuildMemberUpdate(p, room_it->second, mc, cause, ctx->a_variant); break; } case ORBIS_NP_MATCHING2_ROOM_EVENT_MEMBER_LEFT: { @@ -320,7 +363,7 @@ void HandleRoomEvent(const ShadNet::NotifyRoomEvent& n) { if (mem_it == room_it->second.members.end()) { return; } - BuildMemberUpdate(p, room_it->second, mem_it->second, cause); + BuildMemberUpdate(p, room_it->second, mem_it->second, cause, ctx->a_variant); QueueMatching2SignalingEvent(*ctx, room_id, member_id, ORBIS_NP_MATCHING2_SIGNALING_EVENT_DEAD, ORBIS_NP_MATCHING2_SIGNALING_ERROR_TERMINATED_BY_PEER); @@ -463,17 +506,35 @@ void HandleRoomEvent(const ShadNet::NotifyRoomEvent& n) { LOG_DEBUG(Lib_NpMatching2, "RoomEvent ctx={} room={} event={:#x} cause={}", n.ctx_id, n.room_id, n.event, n.event_cause); + OrbisNpMatching2Event fired_event = event; + if (ctx->a_variant) { + switch (event) { + case ORBIS_NP_MATCHING2_ROOM_EVENT_MEMBER_JOINED: + fired_event = ORBIS_NP_MATCHING2_ROOM_EVENT_MEMBER_JOINED_A; + break; + case ORBIS_NP_MATCHING2_ROOM_EVENT_MEMBER_LEFT: + fired_event = ORBIS_NP_MATCHING2_ROOM_EVENT_MEMBER_LEFT_A; + break; + case ORBIS_NP_MATCHING2_ROOM_EVENT_UPDATED_ROOM_MEMBER_DATA_INTERNAL: + fired_event = ORBIS_NP_MATCHING2_ROOM_EVENT_UPDATED_ROOM_MEMBER_DATA_INTERNAL_A; + break; + default: + break; + } + } + PendingEvent ev{}; ev.type = PendingEvent::ROOM_EVENT_CB; ev.ctx_id = ctx->ctx_id; ev.fire_at = std::chrono::steady_clock::now(); ev.room_id = room_id; - ev.room_event = event; + ev.room_event = fired_event; ev.room_event_data = p.room_event_data; ScheduleEvent(std::move(ev)); if (event == ORBIS_NP_MATCHING2_ROOM_EVENT_MEMBER_JOINED) { StartMatching2PeerHandshake(*ctx, room_id, member_id); + QueueMatching2EstablishedForRoomPeers(*ctx, room_id); } } @@ -780,7 +841,7 @@ s32 MmGetWorldInfoList(OrbisNpMatching2ContextId ctx_id, OrbisNpMatching2Request } s32 MmSearchRoom(OrbisNpMatching2ContextId ctx_id, OrbisNpMatching2RequestId req_id, - const OrbisNpMatching2SearchRoomRequest& request) { + const OrbisNpMatching2SearchRoomRequest& request, bool a_variant) { shadnet::SearchRoomRequest req; req.set_world_id(request.worldId); req.set_lobby_id(request.lobbyId); @@ -814,8 +875,29 @@ s32 MmSearchRoom(OrbisNpMatching2ContextId ctx_id, OrbisNpMatching2RequestId req for (u64 i = 0; i < request.attrs; ++i) { req.add_attr_ids(request.attr[i]); } - return MmSubmitRequest(ctx_id, req_id, ORBIS_NP_MATCHING2_REQUEST_EVENT_SEARCH_ROOM, - MmCommand::SearchRoom, MakeProtoPayload(req)); + return MmSubmitRequest(ctx_id, req_id, + a_variant ? ORBIS_NP_MATCHING2_REQUEST_EVENT_SEARCH_ROOM_A + : ORBIS_NP_MATCHING2_REQUEST_EVENT_SEARCH_ROOM, + MmCommand::SearchRoom, MakeProtoPayload(req), a_variant); +} + +s32 MmGetRoomDataExternalList(OrbisNpMatching2ContextId ctx_id, OrbisNpMatching2RequestId req_id, + const OrbisNpMatching2GetRoomDataExternalListRequest& request, + bool a_variant) { + shadnet::GetRoomDataExternalListRequest req; + for (u64 i = 0; i < request.roomIdNum; ++i) { + req.add_room_ids(request.roomId[i]); + } + for (u64 i = 0; i < request.attrIdNum; ++i) { + req.add_attr_ids(request.attrId[i]); + } + LOG_DEBUG(Lib_NpMatching2, "getRoomDataExternalList roomN={} attrN={}", request.roomIdNum, + request.attrIdNum); + return MmSubmitRequest(ctx_id, req_id, + a_variant + ? ORBIS_NP_MATCHING2_REQUEST_EVENT_GET_ROOM_DATA_EXTERNAL_LIST_A + : ORBIS_NP_MATCHING2_REQUEST_EVENT_GET_ROOM_DATA_EXTERNAL_LIST, + MmCommand::GetRoomDataExternalList, MakeProtoPayload(req), a_variant); } s32 MmSetRoomDataInternal(OrbisNpMatching2ContextId ctx_id, OrbisNpMatching2RequestId 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 91853a79b..36af84ce1 100644 --- a/src/core/libraries/np/np_matching2/np_matching2_mm.h +++ b/src/core/libraries/np/np_matching2/np_matching2_mm.h @@ -9,7 +9,6 @@ #include "common/types.h" #include "core/libraries/np/np_matching2/np_matching2.h" -#include "core/libraries/np/np_matching2/np_matching2_types.h" namespace ShadNet { class ShadNetClient; @@ -31,6 +30,7 @@ enum class MmCommand : u16 { SetRoomDataExternal = 21, KickoutRoomMember = 22, GetWorldInfoList = 23, + GetRoomDataExternalList = 24, }; void SetMmShadNetClient(std::shared_ptr client, @@ -61,7 +61,10 @@ s32 MmLeaveRoom(OrbisNpMatching2ContextId ctx_id, OrbisNpMatching2RequestId req_ s32 MmGetWorldInfoList(OrbisNpMatching2ContextId ctx_id, OrbisNpMatching2RequestId req_id, const OrbisNpMatching2GetWorldInfoListRequest& request); s32 MmSearchRoom(OrbisNpMatching2ContextId ctx_id, OrbisNpMatching2RequestId req_id, - const OrbisNpMatching2SearchRoomRequest& request); + const OrbisNpMatching2SearchRoomRequest& request, bool a_variant = false); +s32 MmGetRoomDataExternalList(OrbisNpMatching2ContextId ctx_id, OrbisNpMatching2RequestId req_id, + const OrbisNpMatching2GetRoomDataExternalListRequest& request, + bool a_variant = false); s32 MmSetRoomDataInternal(OrbisNpMatching2ContextId ctx_id, OrbisNpMatching2RequestId req_id, const OrbisNpMatching2SetRoomDataInternalRequest& request); s32 MmSetRoomDataExternal(OrbisNpMatching2ContextId ctx_id, OrbisNpMatching2RequestId req_id, 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..aae016088 100644 --- a/src/core/libraries/np/np_matching2/np_matching2_signaling.cpp +++ b/src/core/libraries/np/np_matching2/np_matching2_signaling.cpp @@ -416,6 +416,20 @@ void StartMatching2SignalingForRoomPeers(ContextObject& ctx, OrbisNpMatching2Roo } } +void QueueMatching2EstablishedForRoomPeers(ContextObject& ctx, OrbisNpMatching2RoomId room_id) { + const auto room_it = ctx.room_cache.find(room_id); + if (room_it == ctx.room_cache.end()) { + return; + } + + for (const auto& [member_id, member] : room_it->second.members) { + if (member_id == 0 || member_id == ctx.my_member_id) { + continue; + } + MarkMatching2PeerActive(ctx, room_id, member_id, member.addr, member.port); + } +} + void QueueMatching2DeadForRoomPeers(ContextObject& ctx, OrbisNpMatching2RoomId room_id, s32 error_code) { auto room_it = ctx.room_cache.find(room_id); diff --git a/src/core/libraries/np/np_matching2/np_matching2_signaling.h b/src/core/libraries/np/np_matching2/np_matching2_signaling.h index a6a632e65..cf57b65e8 100644 --- a/src/core/libraries/np/np_matching2/np_matching2_signaling.h +++ b/src/core/libraries/np/np_matching2/np_matching2_signaling.h @@ -18,6 +18,7 @@ bool SendMatching2StunPing(const ContextObject& ctx); void StartMatching2PeerHandshake(ContextObject& ctx, OrbisNpMatching2RoomId room_id, OrbisNpMatching2RoomMemberId member_id); void StartMatching2SignalingForRoomPeers(ContextObject& ctx, OrbisNpMatching2RoomId room_id); +void QueueMatching2EstablishedForRoomPeers(ContextObject& ctx, OrbisNpMatching2RoomId room_id); void QueueMatching2DeadForRoomPeers(ContextObject& ctx, OrbisNpMatching2RoomId room_id, s32 error_code); void QueueMatching2SignalingEvent(ContextObject& ctx, OrbisNpMatching2RoomId room_id, diff --git a/src/core/libraries/np/np_signaling/np_signaling.cpp b/src/core/libraries/np/np_signaling/np_signaling.cpp index 8ca259b9d..b278e14b1 100644 --- a/src/core/libraries/np/np_signaling/np_signaling.cpp +++ b/src/core/libraries/np/np_signaling/np_signaling.cpp @@ -147,6 +147,8 @@ s32 PS4_SYSV_ABI sceNpSignalingCreateContext(const void* npId, void* callback, v return ORBIS_NP_SIGNALING_ERROR_INVALID_ARGUMENT; } + const bool transport_ready = Stubs::EnsureTransport(); + s32 ctx_id = 0; { SignalingMutexGuard lock; @@ -177,7 +179,7 @@ s32 PS4_SYSV_ABI sceNpSignalingCreateContext(const void* npId, void* callback, v fmt::ptr(callbackArg), ctx.compiled_sdk_version, ctx.bound_port); } - if (Stubs::TransportIsReady()) { + if (transport_ready) { SendStunPing(ctx_id); } return ORBIS_OK; @@ -203,6 +205,8 @@ s32 PS4_SYSV_ABI sceNpSignalingCreateContextA(s32 userId, void* callback, void* // Account id isn't needed without matchmaking wired up; leave it 0 for now. const OrbisNpAccountId account_id = 0; + const bool transport_ready = Stubs::EnsureTransport(); + s32 ctx_id = 0; { SignalingMutexGuard lock; @@ -234,7 +238,7 @@ s32 PS4_SYSV_ABI sceNpSignalingCreateContextA(s32 userId, void* callback, void* OnlineIdToString(ctx.owner_online_id), account_id); } - if (Stubs::TransportIsReady()) { + if (transport_ready) { SendStunPing(ctx_id); } return ORBIS_OK; @@ -297,6 +301,8 @@ s32 PS4_SYSV_ABI sceNpSignalingActivateConnection(OrbisNpSignalingContextId ctxI s32 cid = 0; bool reused_established = false; + bool queue_activation = false; + bool start_handshake = true; { SignalingMutexGuard lock; if (!g_initialized) { @@ -322,12 +328,18 @@ s32 PS4_SYSV_ABI sceNpSignalingActivateConnection(OrbisNpSignalingContextId ctxI } else if (conn_it != g_connections.end()) { cid = existing_it->second; ConnectionInfo& ci = conn_it->second; + const bool was_locally_activated = ci.locally_activated; ci.locally_activated = true; if (ci.state == ConnState::Established) { ClearLingerAndTimeoutLocked(cid); reused_established = true; + start_handshake = false; } else { ClearLingerAndTimeoutLocked(cid); + start_handshake = true; + } + if (!was_locally_activated) { + queue_activation = true; } } } @@ -352,23 +364,30 @@ s32 PS4_SYSV_ABI sceNpSignalingActivateConnection(OrbisNpSignalingContextId ctxI } if (created_new) { ArmConnectTimeoutLocked(cid); - QueueActivationLocked(cid, peer_online_id_str); + queue_activation = true; + start_handshake = true; + } + if (queue_activation) { + QueueActivationLocked(cid, peer_online_id_str, start_handshake); } LOG_INFO(Lib_NpSignaling, "ctxId={} peer='{}' connId={} Status: {}", ctxId, peer_online_id_str, cid, created_new ? "queued, async" - : reused_established ? "reused established" + : reused_established ? "queued local activation on established connection" + : queue_activation ? "queued local activation on existing connection" : "reused transient"); } *outConnId = cid; - if (reused_established) { - EstablishConnection(cid, false); + if (queue_activation) { + g_dispatch_cv.notify_all(); return ORBIS_OK; } - g_dispatch_cv.notify_all(); + if (reused_established) { + EstablishConnection(cid, false); + } return ORBIS_OK; } diff --git a/src/core/libraries/np/np_signaling/np_signaling.h b/src/core/libraries/np/np_signaling/np_signaling.h index 31a660d1d..357728dbe 100644 --- a/src/core/libraries/np/np_signaling/np_signaling.h +++ b/src/core/libraries/np/np_signaling/np_signaling.h @@ -6,6 +6,7 @@ #include #include "common/types.h" +#include "core/libraries/np/np_types2.h" namespace Core::Loader { class SymbolsResolver; @@ -13,66 +14,6 @@ class SymbolsResolver; namespace Libraries::Np::NpSignaling { -using OrbisNpSignalingContextId = s32; -using OrbisNpSignalingConnectionId = s32; -using OrbisNpSignalingRequestId = u32; - -using OrbisNpSignalingHandler = PS4_SYSV_ABI void (*)(u32 ctxId, u32 connId, s32 event, - s32 errorCode, void* userArg); - -constexpr s32 ORBIS_NP_SIGNALING_EVENT_DEAD = 0; -constexpr s32 ORBIS_NP_SIGNALING_EVENT_ESTABLISHED = 1; -constexpr s32 ORBIS_NP_SIGNALING_EVENT_NETINFO_ERROR = 2; -constexpr s32 ORBIS_NP_SIGNALING_EVENT_NETINFO_RESULT = 3; -constexpr s32 ORBIS_NP_SIGNALING_EVENT_PEER_ACTIVATED = 10; -constexpr s32 ORBIS_NP_SIGNALING_EVENT_PEER_DEACTIVATED = 11; -constexpr s32 ORBIS_NP_SIGNALING_EVENT_MUTUAL_ACTIVATED = 12; - -constexpr s32 ORBIS_NP_SIGNALING_CONN_STATUS_INACTIVE = 0; -constexpr s32 ORBIS_NP_SIGNALING_CONN_STATUS_PENDING = 1; -constexpr s32 ORBIS_NP_SIGNALING_CONN_STATUS_ACTIVE = 2; - -constexpr s32 ORBIS_NP_SIGNALING_CONN_INFO_RTT = 1; -constexpr s32 ORBIS_NP_SIGNALING_CONN_INFO_BANDWIDTH = 2; -constexpr s32 ORBIS_NP_SIGNALING_CONN_INFO_PEER_NP_ID = 3; -constexpr s32 ORBIS_NP_SIGNALING_CONN_INFO_PEER_ADDR = 4; -constexpr s32 ORBIS_NP_SIGNALING_CONN_INFO_MAPPED_ADDR = 5; -constexpr s32 ORBIS_NP_SIGNALING_CONN_INFO_PACKET_LOSS = 6; -constexpr s32 ORBIS_NP_SIGNALING_CONN_INFO_PEER_ADDRESS_A = 7; - -constexpr s32 ORBIS_NP_SIGNALING_CONTEXT_OPTION_FLAG = 1; - -struct OrbisNpSignalingNetInfo { - u64 size; - u32 localAddr; - u32 mappedAddr; - s32 natStatus; - u32 _pad_14; -}; -static_assert(sizeof(OrbisNpSignalingNetInfo) == 0x18); - -struct OrbisNpSignalingAccountPlatformPair { - u64 accountId; - u32 platformType; - u32 _pad_0c; -}; -static_assert(sizeof(OrbisNpSignalingAccountPlatformPair) == 0x10); - -struct OrbisNpSignalingMemoryInfo { - u64 currentInUse; - u64 peakInUse; - u64 maxSystemSize; -}; -static_assert(sizeof(OrbisNpSignalingMemoryInfo) == 0x18); - -struct OrbisNpSignalingConnectionStatistics { - u32 peakConnectionCount; - u32 activeConnectionCount; - u32 transientConnectionCount; - u32 establishedConnectionCount; -}; -static_assert(sizeof(OrbisNpSignalingConnectionStatistics) == 0x10); - s32 PS4_SYSV_ABI sceNpSignalingInitialize(s64 memorySize, s32 threadPriority, s32 cpuAffinityMask, s64 threadStackSize); s32 PS4_SYSV_ABI sceNpSignalingTerminate(); diff --git a/src/core/libraries/np/np_signaling/np_signaling_helpers.cpp b/src/core/libraries/np/np_signaling/np_signaling_helpers.cpp index 65db54b09..651d357db 100644 --- a/src/core/libraries/np/np_signaling/np_signaling_helpers.cpp +++ b/src/core/libraries/np/np_signaling/np_signaling_helpers.cpp @@ -370,7 +370,7 @@ static void StopReceiveThread() { static void PingThreadMain() { while (!g_ping_stop) { - if (!Stubs::TransportIsReady()) { + if (!Stubs::EnsureTransport()) { std::this_thread::sleep_for(std::chrono::milliseconds(kSigRetryMs)); continue; } @@ -400,6 +400,7 @@ static void PingThreadMain() { StunPing ping{}; ping.cmd = 0x01; std::memcpy(ping.online_id, cs.online_id.data, ORBIS_NP_ONLINEID_MAX_LENGTH); + ping.local_ip = Stubs::AdvertisedAddr(); Stubs::SignalingSendTo(&ping, sizeof(ping), server_addr, server_port); } 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 4e50dc8f4..26cd9a2cd 100644 --- a/src/core/libraries/np/np_signaling/np_signaling_state.cpp +++ b/src/core/libraries/np/np_signaling/np_signaling_state.cpp @@ -897,8 +897,9 @@ void StartHandshakeInitiator(OrbisNpSignalingConnectionId conn_id) { } } -void QueueActivationLocked(OrbisNpSignalingConnectionId conn_id, std::string_view peer_online_id) { - g_pending_activations.push_back({conn_id, std::string(peer_online_id)}); +void QueueActivationLocked(OrbisNpSignalingConnectionId conn_id, std::string_view peer_online_id, + bool start_handshake) { + g_pending_activations.push_back({conn_id, std::string(peer_online_id), start_handshake}); } void ProcessPendingActivations() { @@ -912,6 +913,7 @@ void ProcessPendingActivations() { } for (const PendingActivation& act : work) { + bool already_established = false; { SignalingMutexGuard lock; const auto it = g_connections.find(act.conn_id); @@ -940,8 +942,16 @@ void ProcessPendingActivations() { it->second.addr = peer_addr; it->second.port = peer_port; SendActivationRequestLocked(it->second); + already_established = it->second.state == ConnState::Established; + LOG_INFO(Lib_NpSignaling, "connection {} sent local activation to '{}' at {:#x}:{}{}", + act.conn_id, act.peer_online_id, peer_addr, sceNetNtohs(peer_port), + act.start_handshake ? "" : " (existing connection)"); + } + if (act.start_handshake) { + StartHandshakeInitiator(act.conn_id); + } else if (already_established) { + EstablishConnection(act.conn_id, false); } - StartHandshakeInitiator(act.conn_id); } } @@ -1154,11 +1164,16 @@ void SendActivationRequestLocked(const ConnectionInfo& ci) { void SendControlCloseLocked(const ConnectionInfo& ci, ControlReason reason) { if (ci.addr == 0 || ci.port == 0) { + LOG_WARNING(Lib_NpSignaling, + "Control Close SEND skipped: connId={} reason={} unresolved endpoint", + ci.conn_id, static_cast(reason)); return; } SignalingControl pkt = MakeControlLocked(ci, ControlKind::Close); pkt.reason = static_cast(reason); - Stubs::ControlSendTo(&pkt, sizeof(pkt), ci.addr, ci.port); + const int rc = Stubs::ControlSendTo(&pkt, sizeof(pkt), ci.addr, ci.port); + LOG_INFO(Lib_NpSignaling, "Control Close SEND: connId={} reason={} dst={:#x}:{} rc={}", + ci.conn_id, static_cast(reason), ci.addr, sceNetNtohs(ci.port), rc); } void HandleControlPacket(u32 from_addr, u16 from_port, const SignalingControl& pkt) { @@ -1236,6 +1251,9 @@ void HandleControlPacket(u32 from_addr, u16 from_port, const SignalingControl& p ack_addr = ci.addr; ack_port = ci.port; } else if (conn_id == 0) { + LOG_INFO(Lib_NpSignaling, + "Control RECV ignored: kind={} from='{}' src={:#x}:{} no matching connection", + pkt.kind, from_id, from_addr, sceNetNtohs(from_port)); return; } else if (kind == ControlKind::ActivationAck) { ConnectionInfo& ci = g_connections[conn_id]; @@ -1252,6 +1270,10 @@ void HandleControlPacket(u32 from_addr, u16 from_port, const SignalingControl& p } else if (kind == ControlKind::Close) { ConnectionInfo& ci = g_connections[conn_id]; const ControlReason reason = static_cast(pkt.reason); + LOG_INFO(Lib_NpSignaling, + "Control Close RECV: connId={} from='{}' reason={} src={:#x}:{} state={}", + conn_id, from_id, pkt.reason, from_addr, sceNetNtohs(from_port), + static_cast(ci.state)); if (reason == ControlReason::Deactivate && ci.state == ConnState::Established) { peer_deactivated_conn = conn_id; } else { @@ -1290,7 +1312,7 @@ void SendStunPing(s32 ctx_id) { online_id = it->second.owner_online_id; } - if (!Stubs::TransportIsReady()) { + if (!Stubs::EnsureTransport()) { return; } @@ -1306,9 +1328,10 @@ void SendStunPing(s32 ctx_id) { StunPing ping{}; ping.cmd = 0x01; std::memcpy(ping.online_id, online_id.data, ORBIS_NP_ONLINEID_MAX_LENGTH); + ping.local_ip = Stubs::AdvertisedAddr(); - LOG_DEBUG(Lib_NpSignaling, "ctxId={} online_id='{}' server={:#x}:{}", ctx_id, - OnlineIdToString(online_id), server_addr, sceNetNtohs(server_udp)); + LOG_DEBUG(Lib_NpSignaling, "ctxId={} online_id='{}' server={:#x}:{} local_ip={:#x}", ctx_id, + OnlineIdToString(online_id), server_addr, sceNetNtohs(server_udp), ping.local_ip); Stubs::SignalingSendTo(&ping, sizeof(ping), server_addr, server_udp); } diff --git a/src/core/libraries/np/np_signaling/np_signaling_state.h b/src/core/libraries/np/np_signaling/np_signaling_state.h index 3d0e7c662..d923fba2f 100644 --- a/src/core/libraries/np/np_signaling/np_signaling_state.h +++ b/src/core/libraries/np/np_signaling/np_signaling_state.h @@ -253,6 +253,7 @@ extern std::unordered_map g_peer_netinfo_results; struct PendingActivation { OrbisNpSignalingConnectionId conn_id = 0; std::string peer_online_id; + bool start_handshake = true; }; extern std::vector g_pending_activations; extern u32 g_peer_netinfo_next_id; @@ -331,7 +332,8 @@ void TerminateConnectionFaithful(OrbisNpSignalingConnectionId conn_id); void StartHandshakeInitiator(OrbisNpSignalingConnectionId conn_id); -void QueueActivationLocked(OrbisNpSignalingConnectionId conn_id, std::string_view peer_online_id); +void QueueActivationLocked(OrbisNpSignalingConnectionId conn_id, std::string_view peer_online_id, + bool start_handshake = true); void ProcessPendingActivations(); void HandleHandshakePacket(u32 from_addr, u16 from_port, const SignalingHandshake& pkt); diff --git a/src/core/libraries/np/np_matching2/np_matching2_types.h b/src/core/libraries/np/np_types2.h similarity index 60% rename from src/core/libraries/np/np_matching2/np_matching2_types.h rename to src/core/libraries/np/np_types2.h index 0d9c0f8ee..d0300f339 100644 --- a/src/core/libraries/np/np_matching2/np_matching2_types.h +++ b/src/core/libraries/np/np_types2.h @@ -4,52 +4,227 @@ #pragma once #include "common/types.h" -#include "core/libraries/np/np_matching2/np_matching2.h" #include "core/libraries/np/np_types.h" #include "core/libraries/rtc/rtc.h" #include "core/libraries/system/userservice.h" namespace Libraries::Np::NpMatching2 { -struct OrbisNpMatching2RoomGroup; -struct OrbisNpMatching2RoomGroupInfo; -struct OrbisNpMatching2RoomBinAttrInternal; -struct OrbisNpMatching2RoomMemberBinAttrInternal; +// Constants for matching functions and structures +constexpr u32 ORBIS_NP_MATCHING2_SESSION_PASSWORD_SIZE = 8; +constexpr u32 ORBIS_NP_MATCHING2_GROUP_LABEL_SIZE = 8; +// Default initialization values +enum OrbisNpMatching2InitDefault : u64 { + ORBIS_NP_MATCHING2_THREAD_STACK_SIZE_DEFAULT = 32768, + ORBIS_NP_MATCHING2_POOLSIZE_DEFAULT = 131072, + ORBIS_NP_MATCHING2_SSL_POOLSIZE_DEFAULT = 196608, +}; + +using OrbisNpMatching2AttributeId = u16; +using OrbisNpMatching2BlockKickFlag = u8; +using OrbisNpMatching2ContextId = u16; +using OrbisNpMatching2FlagAttr = u32; +using OrbisNpMatching2Flags = u32; +using OrbisNpMatching2LobbyId = u64; +using OrbisNpMatching2LobbyMemberId = u16; +using OrbisNpMatching2NatType = u8; +using OrbisNpMatching2Operator = u8; +using OrbisNpMatching2RequestId = u32; +using OrbisNpMatching2RoomGroupId = u8; +using OrbisNpMatching2RoomId = u64; +using OrbisNpMatching2RoomMemberId = u16; +using OrbisNpMatching2RoomPasswordSlotMask = u64; +using OrbisNpMatching2ServerId = u16; +using OrbisNpMatching2SignalingFlag = u8; +using OrbisNpMatching2SignalingRequestId = u32; +using OrbisNpMatching2TeamId = u8; +using OrbisNpMatching2WorldId = u32; + +// Event of request/room/signaling/context functions +enum OrbisNpMatching2Event : u16 { + ORBIS_NP_MATCHING2_REQUEST_EVENT_GET_WORLD_INFO_LIST = 0x0002, + ORBIS_NP_MATCHING2_REQUEST_EVENT_SET_ROOM_DATA_EXTERNAL = 0x0004, + ORBIS_NP_MATCHING2_REQUEST_EVENT_GET_ROOM_DATA_EXTERNAL_LIST = 0x0005, + ORBIS_NP_MATCHING2_REQUEST_EVENT_SET_USER_INFO = 0x0007, + ORBIS_NP_MATCHING2_REQUEST_EVENT_CREATE_JOIN_ROOM = 0x0101, + ORBIS_NP_MATCHING2_REQUEST_EVENT_JOIN_ROOM = 0x0102, + ORBIS_NP_MATCHING2_REQUEST_EVENT_LEAVE_ROOM = 0x0103, + ORBIS_NP_MATCHING2_REQUEST_EVENT_KICKOUT_ROOM_MEMBER = 0x0104, + ORBIS_NP_MATCHING2_REQUEST_EVENT_GRANT_ROOM_OWNER = 0x0105, + ORBIS_NP_MATCHING2_REQUEST_EVENT_SEARCH_ROOM = 0x0106, + ORBIS_NP_MATCHING2_REQUEST_EVENT_SEND_ROOM_MESSAGE = 0x0108, + ORBIS_NP_MATCHING2_REQUEST_EVENT_SET_ROOM_DATA_INTERNAL = 0x0109, + ORBIS_NP_MATCHING2_REQUEST_EVENT_GET_ROOM_DATA_INTERNAL = 0x010A, + ORBIS_NP_MATCHING2_REQUEST_EVENT_JOIN_LOBBY = 0x0201, + ORBIS_NP_MATCHING2_REQUEST_EVENT_SIGNALING_GET_PING_INFO = 0x0E01, + ORBIS_NP_MATCHING2_ROOM_EVENT_MEMBER_JOINED = 0x1101, + ORBIS_NP_MATCHING2_ROOM_EVENT_MEMBER_LEFT = 0x1102, + ORBIS_NP_MATCHING2_ROOM_EVENT_KICKEDOUT = 0x1103, + ORBIS_NP_MATCHING2_ROOM_EVENT_ROOM_DESTROYED = 0x1104, + ORBIS_NP_MATCHING2_ROOM_EVENT_ROOM_OWNER_CHANGED = 0x1105, + ORBIS_NP_MATCHING2_ROOM_EVENT_UPDATED_ROOM_DATA_INTERNAL = 0x1106, + ORBIS_NP_MATCHING2_ROOM_EVENT_UPDATED_ROOM_MEMBER_DATA_INTERNAL = 0x1107, + ORBIS_NP_MATCHING2_ROOM_EVENT_UPDATED_SIGNALING_OPT_PARAM = 0x1108, + ORBIS_NP_MATCHING2_SIGNALING_EVENT_DEAD = 0x5101, + ORBIS_NP_MATCHING2_SIGNALING_EVENT_ESTABLISHED = 0x5102, + ORBIS_NP_MATCHING2_SIGNALING_EVENT_NETINFO_ERROR = 0x5103, + ORBIS_NP_MATCHING2_CONTEXT_EVENT_START_OVER = 0x6F01, + ORBIS_NP_MATCHING2_CONTEXT_EVENT_STARTED = 0x6F02, + ORBIS_NP_MATCHING2_CONTEXT_EVENT_STOPPED = 0x6F03, + ORBIS_NP_MATCHING2_REQUEST_EVENT_CREATE_JOIN_ROOM_A = 0x7101, + ORBIS_NP_MATCHING2_REQUEST_EVENT_JOIN_ROOM_A = 0x7102, + ORBIS_NP_MATCHING2_REQUEST_EVENT_GET_ROOM_DATA_EXTERNAL_LIST_A = 0x7005, + ORBIS_NP_MATCHING2_REQUEST_EVENT_SEARCH_ROOM_A = 0x7106, + ORBIS_NP_MATCHING2_ROOM_EVENT_MEMBER_JOINED_A = 0x8101, + ORBIS_NP_MATCHING2_ROOM_EVENT_MEMBER_LEFT_A = 0x8102, + ORBIS_NP_MATCHING2_ROOM_EVENT_UPDATED_ROOM_MEMBER_DATA_INTERNAL_A = 0x8107, + ORBIS_NP_MATCHING2_ROOM_MSG_EVENT_MESSAGE_A = 0x9102, +}; + +// Event cause +enum OrbisNpMatching2EventCause : u8 { + ORBIS_NP_MATCHING2_EVENT_CAUSE_LEAVE_ACTION = 1, + ORBIS_NP_MATCHING2_EVENT_CAUSE_KICKOUT_ACTION = 2, + ORBIS_NP_MATCHING2_EVENT_CAUSE_GRANT_OWNER_ACTION = 3, + ORBIS_NP_MATCHING2_EVENT_CAUSE_SERVER_OPERATION = 4, + ORBIS_NP_MATCHING2_EVENT_CAUSE_MEMBER_DISAPPEARED = 5, + ORBIS_NP_MATCHING2_EVENT_CAUSE_SERVER_INTERNAL = 6, + ORBIS_NP_MATCHING2_EVENT_CAUSE_CONNECTION_ERROR = 7, + ORBIS_NP_MATCHING2_EVENT_CAUSE_NP_SIGNED_OUT = 8, + ORBIS_NP_MATCHING2_EVENT_CAUSE_SYSTEM_ERROR = 9, + ORBIS_NP_MATCHING2_EVENT_CAUSE_CONTEXT_ERROR = 10, + ORBIS_NP_MATCHING2_EVENT_CAUSE_CONTEXT_ACTION = 11, +}; + +// Signaling type +enum OrbisNpMatching2SignalingType : u8 { + ORBIS_NP_MATCHING2_SIGNALING_TYPE_NONE = 0, + ORBIS_NP_MATCHING2_SIGNALING_TYPE_MESH = 1, + ORBIS_NP_MATCHING2_SIGNALING_TYPE_STAR = 2, +}; + +// Type of connection information to acquire +enum OrbisNpMatching2SignalingConnectionInfoType : s32 { + ORBIS_NP_MATCHING2_SIGNALING_CONN_INFO_RTT = 1, + ORBIS_NP_MATCHING2_SIGNALING_CONN_INFO_BANDWIDTH = 2, + ORBIS_NP_MATCHING2_SIGNALING_CONN_INFO_PEER_NP_ID = 3, + ORBIS_NP_MATCHING2_SIGNALING_CONN_INFO_PEER_ADDR = 4, + ORBIS_NP_MATCHING2_SIGNALING_CONN_INFO_MAPPED_ADDR = 5, + ORBIS_NP_MATCHING2_SIGNALING_CONN_INFO_PACKET_LOSS = 6, + ORBIS_NP_MATCHING2_SIGNALING_CONN_INFO_PEER_NPID = 7, + ORBIS_NP_MATCHING2_SIGNALING_CONN_INFO_PEER_ADDRESS_A = 7, +}; + +// Attribute IDs of external/internal room and room member binary attributes +enum OrbisNpMatching2AttrId : OrbisNpMatching2AttributeId { + ORBIS_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_1_ID = 0x004C, + ORBIS_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_2_ID = 0x004D, + ORBIS_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_3_ID = 0x004E, + ORBIS_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_4_ID = 0x004F, + ORBIS_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_5_ID = 0x0050, + ORBIS_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_6_ID = 0x0051, + ORBIS_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_7_ID = 0x0052, + ORBIS_NP_MATCHING2_ROOM_SEARCHABLE_INT_ATTR_EXTERNAL_8_ID = 0x0053, + ORBIS_NP_MATCHING2_ROOM_SEARCHABLE_BIN_ATTR_EXTERNAL_1_ID = 0x0054, + ORBIS_NP_MATCHING2_ROOM_BIN_ATTR_EXTERNAL_1_ID = 0x0055, + ORBIS_NP_MATCHING2_ROOM_BIN_ATTR_EXTERNAL_2_ID = 0x0056, + ORBIS_NP_MATCHING2_ROOM_BIN_ATTR_INTERNAL_1_ID = 0x0057, + ORBIS_NP_MATCHING2_ROOM_BIN_ATTR_INTERNAL_2_ID = 0x0058, + ORBIS_NP_MATCHING2_ROOMMEMBER_BIN_ATTR_INTERNAL_1_ID = 0x0059, +}; + +// Flag-type room attribute +enum OrbisNpMatching2RoomFlagAttr : OrbisNpMatching2Flags { + ORBIS_NP_MATCHING2_ROOM_FLAG_ATTR_OWNER_AUTO_GRANT = 0x80000000, + ORBIS_NP_MATCHING2_ROOM_FLAG_ATTR_CLOSED = 0x40000000, + ORBIS_NP_MATCHING2_ROOM_FLAG_ATTR_FULL = 0x20000000, + ORBIS_NP_MATCHING2_ROOM_FLAG_ATTR_HIDDEN = 0x10000000, + ORBIS_NP_MATCHING2_ROOM_FLAG_ATTR_NAT_TYPE_RESTRICTION = 0x04000000, + ORBIS_NP_MATCHING2_ROOM_FLAG_ATTR_PROHIBITIVE_MODE = 0x02000000, +}; + +// Flag-type room member attribute +enum OrbisNpMatching2RoomMemberFlagAttr : OrbisNpMatching2Flags { + ORBIS_NP_MATCHING2_ROOMMEMBER_FLAG_ATTR_OWNER = 0x80000000, +}; + +// Member role +enum OrbisNpMatching2Role : u8 { + ORBIS_NP_MATCHING2_ROLE_MEMBER = 1, + ORBIS_NP_MATCHING2_ROLE_OWNER = 2, +}; + +// Context callback function using OrbisNpMatching2ContextCallback = PS4_SYSV_ABI void (*)(OrbisNpMatching2ContextId contextId, OrbisNpMatching2Event event, OrbisNpMatching2EventCause cause, int errorCode, void* userdata); +// Lobby event callback function using OrbisNpMatching2LobbyEventCallback = PS4_SYSV_ABI void (*)(OrbisNpMatching2ContextId contextId, OrbisNpMatching2LobbyId lobbyId, OrbisNpMatching2Event event, const void* data, void* userdata); +// Lobby message callback function using OrbisNpMatching2LobbyMessageCallback = PS4_SYSV_ABI void (*)(OrbisNpMatching2ContextId contextId, OrbisNpMatching2LobbyId lobbyId, OrbisNpMatching2LobbyMemberId srcMemberId, OrbisNpMatching2Event event, const void* data, void* userdata); +// Request callback function using OrbisNpMatching2RequestCallback = PS4_SYSV_ABI void (*)(OrbisNpMatching2ContextId, OrbisNpMatching2RequestId, OrbisNpMatching2Event, int, const void*, void*); +// Room event callback function using OrbisNpMatching2RoomEventCallback = PS4_SYSV_ABI void (*)(OrbisNpMatching2ContextId contextId, OrbisNpMatching2RoomId roomId, OrbisNpMatching2Event event, const void* data, void* userdata); +// Room message callback function using OrbisNpMatching2RoomMessageCallback = PS4_SYSV_ABI void (*)(OrbisNpMatching2ContextId contextId, OrbisNpMatching2RoomId roomId, OrbisNpMatching2RoomMemberId srcMemberId, OrbisNpMatching2Event event, const void* data, void* userdata); +// Signaling callback function using OrbisNpMatching2SignalingCallback = PS4_SYSV_ABI void (*)(OrbisNpMatching2ContextId contextId, OrbisNpMatching2RoomId roomId, OrbisNpMatching2RoomMemberId roomMemberId, OrbisNpMatching2Event event, int errorCode, void* userdata); +struct OrbisNpMatching2RoomGroup; +struct OrbisNpMatching2RoomGroupInfo; +struct OrbisNpMatching2RoomBinAttrInternal; +struct OrbisNpMatching2RoomMemberBinAttrInternal; + +// Session password +struct OrbisNpMatching2SessionPassword { + u8 data[8]; +}; + +// Group label +struct OrbisNpMatching2GroupLabel { + u8 data[8]; +}; + +// Optional presence data +struct OrbisNpMatching2PresenceOptionData { + u8 data[16]; + u64 len; +}; + +// Integer-type attribute +struct OrbisNpMatching2IntAttr { + OrbisNpMatching2AttributeId id; + u8 padding[2]; + u32 num; +}; + +// Binary-type attribute struct OrbisNpMatching2BinAttr { OrbisNpMatching2AttributeId id; u8 pad[6]; @@ -57,6 +232,243 @@ struct OrbisNpMatching2BinAttr { u64 dataSize; }; +// Range filter +struct OrbisNpMatching2RangeFilter { + u32 start; + u32 max; +}; + +// Integer-type search condition +struct OrbisNpMatching2IntSearchFilter { + OrbisNpMatching2Operator searchOperator; + u8 padding[7]; + OrbisNpMatching2IntAttr attr; +}; + +// Binary-type search condition +struct OrbisNpMatching2BinSearchFilter { + OrbisNpMatching2Operator searchOperator; + u8 padding[7]; + OrbisNpMatching2BinAttr attr; +}; + +// Range of result +struct OrbisNpMatching2Range { + u32 start; + u32 total; + u32 results; + u8 pad[4]; +}; + +// Signaling optional parameter +struct OrbisNpMatching2SignalingOptParam { + OrbisNpMatching2SignalingType type; + OrbisNpMatching2SignalingFlag flag; + OrbisNpMatching2RoomMemberId memberId; + u8 padding[4]; +}; + +// Set groups in a room +struct OrbisNpMatching2RoomGroupConfig { + u32 slots; + bool hasLabel; + OrbisNpMatching2GroupLabel label; + bool hasPassword; + u8 pad[2]; +}; + +// Set group password +struct OrbisNpMatching2RoomGroupPasswordConfig { + OrbisNpMatching2RoomGroupId groupId; + bool hasPassword; + u8 pad[1]; +}; + +// Group (of slots in a room) +struct OrbisNpMatching2RoomGroup { + OrbisNpMatching2RoomGroupId id; + bool hasPasswd; + bool hasLabel; + u8 pad; + OrbisNpMatching2GroupLabel label; + u32 slots; + u32 groupMembers; +}; + +// Group information +struct OrbisNpMatching2RoomGroupInfo { + OrbisNpMatching2RoomGroupId id; + bool hasPasswd; + u8 pad[2]; + u32 slots; + u32 groupMembers; +}; + +// Room-internal binary attribute +struct OrbisNpMatching2RoomBinAttrInternal { + Libraries::Rtc::OrbisRtcTick lastUpdate; + OrbisNpMatching2RoomMemberId memberId; + u8 pad[6]; + OrbisNpMatching2BinAttr binAttr; +}; + +// Room member internal binary attribute +struct OrbisNpMatching2RoomMemberBinAttrInternal { + Libraries::Rtc::OrbisRtcTick lastUpdate; + OrbisNpMatching2BinAttr binAttr; +}; + +// Server +struct OrbisNpMatching2World { + OrbisNpMatching2World* next; + OrbisNpMatching2WorldId worldId; + u32 lobbiesNum; + u32 maxLobbyMembersNum; + u32 lobbyMembersNum; + u32 roomsNum; + u32 roomMembersNum; + u8 pad[3]; +}; + +// Room-internal room information +struct OrbisNpMatching2RoomDataInternal { + u16 publicSlots; + u16 privateSlots; + u16 openPublicSlots; + u16 openPrivateSlots; + u16 maxSlot; + OrbisNpMatching2ServerId serverId; + OrbisNpMatching2WorldId worldId; + OrbisNpMatching2LobbyId lobbyId; + OrbisNpMatching2RoomId roomId; + OrbisNpMatching2RoomPasswordSlotMask passwdSlotMask; + u64 joinedSlotMask; + OrbisNpMatching2RoomGroup* roomGroup; + u64 roomGroups; + OrbisNpMatching2Flags flags; + u8 pad[4]; + OrbisNpMatching2RoomBinAttrInternal* internalBinAttr; + u64 internalBinAttrs; +}; + +// Room-external room information +struct OrbisNpMatching2RoomDataExternal { + OrbisNpMatching2RoomDataExternal* next; + u16 maxSlot; + u16 curMembers; + OrbisNpMatching2Flags flags; + OrbisNpMatching2ServerId serverId; + u8 pad[2]; + OrbisNpMatching2WorldId worldId; + OrbisNpMatching2LobbyId lobbyId; + OrbisNpMatching2RoomId roomId; + u64 passwdSlotMask; + u64 joinedSlotMask; + u16 publicSlots; + u16 privateSlots; + u16 openPublicSlots; + u16 openPrivateSlots; + Libraries::Np::OrbisNpId* ownerNpId; + OrbisNpMatching2RoomGroupInfo* roomGroup; + u64 roomGroups; + OrbisNpMatching2IntAttr* externalSearchIntAttr; + u64 externalSearchIntAttrs; + OrbisNpMatching2BinAttr* externalSearchBinAttr; + u64 externalSearchBinAttrs; + OrbisNpMatching2BinAttr* externalBinAttr; + u64 externalBinAttrs; +}; + +// Room-external room information (account-id variant) +struct OrbisNpMatching2RoomDataExternalA { + OrbisNpMatching2RoomDataExternalA* next; + u16 maxSlot; + u16 curMembers; + OrbisNpMatching2Flags flags; + OrbisNpMatching2ServerId serverId; + u8 pad[2]; + OrbisNpMatching2WorldId worldId; + OrbisNpMatching2LobbyId lobbyId; + OrbisNpMatching2RoomId roomId; + OrbisNpMatching2RoomPasswordSlotMask passwdSlotMask; + u64 joinedSlotMask; + u16 publicSlots; + u16 privateSlots; + u16 openPublicSlots; + u16 openPrivateSlots; + Libraries::Np::OrbisNpPeerAddressA owner; + Libraries::Np::OrbisNpOnlineId ownerOnlineId; + OrbisNpMatching2RoomGroupInfo* roomGroup; + u64 roomGroups; + OrbisNpMatching2IntAttr* externalSearchIntAttr; + u64 externalSearchIntAttrs; + OrbisNpMatching2BinAttr* externalSearchBinAttr; + u64 externalSearchBinAttrs; + OrbisNpMatching2BinAttr* externalBinAttr; + u64 externalBinAttrs; +}; + +// Room-internal room member information +struct OrbisNpMatching2RoomMemberDataInternal { + OrbisNpMatching2RoomMemberDataInternal* next; + u64 joinDate; + Libraries::Np::OrbisNpId npId; + u8 pad[4]; + OrbisNpMatching2RoomMemberId memberId; + OrbisNpMatching2TeamId teamId; + OrbisNpMatching2NatType natType; + OrbisNpMatching2Flags flagAttr; + OrbisNpMatching2RoomGroup* roomGroup; + OrbisNpMatching2RoomMemberBinAttrInternal* roomMemberBinAttrInternal; + u64 roomMemberBinAttrInternalNum; +}; +static_assert(sizeof(OrbisNpMatching2RoomMemberDataInternal) == 0x58); + +// Room-internal room member information (account-id variant) +struct OrbisNpMatching2RoomMemberDataInternalA { + OrbisNpMatching2RoomMemberDataInternalA* next; + Libraries::Rtc::OrbisRtcTick joinDateTicks; + Libraries::Np::OrbisNpPeerAddressA user; + Libraries::Np::OrbisNpOnlineId onlineId; + u8 pad[4]; + OrbisNpMatching2RoomMemberId memberId; + OrbisNpMatching2TeamId teamId; + OrbisNpMatching2NatType natType; + OrbisNpMatching2Flags flags; + OrbisNpMatching2RoomGroup* roomGroup; + OrbisNpMatching2RoomMemberBinAttrInternal* roomMemberInternalBinAttr; + u64 roomMemberInternalBinAttrs; +}; + +// Room member ID list +struct OrbisNpMatching2RoomMemberDataInternalList { + OrbisNpMatching2RoomMemberDataInternal* members; + u64 membersNum; + OrbisNpMatching2RoomMemberDataInternal* me; + OrbisNpMatching2RoomMemberDataInternal* owner; +}; + +// Room member ID list (account-id variant) +struct OrbisNpMatching2RoomMemberDataInternalListA { + OrbisNpMatching2RoomMemberDataInternalA* members; + u64 membersNum; + OrbisNpMatching2RoomMemberDataInternalA* me; + OrbisNpMatching2RoomMemberDataInternalA* owner; +}; + +// Initialization parameter +struct OrbisNpMatching2InitializeParameter { + u64 poolSize; + u64 unknown; + s32 priority; + u8 padding[4]; + u64 stackSize; + u64 size; + u64 sslPoolSize; +}; +static_assert(sizeof(OrbisNpMatching2InitializeParameter) == 0x30); + +// Create context parameter struct OrbisNpMatching2CreateContextParameter { Libraries::Np::OrbisNpId* npId; void* npCommunicationId; @@ -66,6 +478,7 @@ struct OrbisNpMatching2CreateContextParameter { }; static_assert(sizeof(OrbisNpMatching2CreateContextParameter) == 0x28); +// Create context parameter (account-id variant) struct OrbisNpMatching2CreateContextParameterA { Libraries::UserService::OrbisUserServiceUserId userId; Libraries::Np::OrbisNpServiceLabel serviceLabel; @@ -73,19 +486,27 @@ struct OrbisNpMatching2CreateContextParameterA { }; static_assert(sizeof(OrbisNpMatching2CreateContextParameterA) == 16); -struct OrbisNpMatching2IntAttr { - OrbisNpMatching2AttributeId id; +// Request optional parameter +struct OrbisNpMatching2RequestOptParam { + OrbisNpMatching2RequestCallback callback; + void* arg; + u32 timeout; + u16 appId; u8 padding[2]; - u32 num; }; -struct OrbisNpMatching2SignalingOptParam { - OrbisNpMatching2SignalingType type; - OrbisNpMatching2SignalingFlag flag; - OrbisNpMatching2RoomMemberId memberId; - u8 padding[4]; +// GetWorldInfoList request +struct OrbisNpMatching2GetWorldInfoListRequest { + OrbisNpMatching2ServerId serverId; }; +// GetWorldInfoList response +struct OrbisNpMatching2GetWorldInfoListResponse { + OrbisNpMatching2World* world; + u64 worldNum; +}; + +// CreateJoinRoom request struct OrbisNpMatching2CreateJoinRoomRequest { u16 maxSlot; OrbisNpMatching2TeamId teamId; @@ -116,6 +537,7 @@ struct OrbisNpMatching2CreateJoinRoomRequest { }; static_assert(sizeof(OrbisNpMatching2CreateJoinRoomRequest) == 184); +// CreateJoinRoom request (account-id variant) struct OrbisNpMatching2CreateJoinRoomRequestA { u16 maxSlot; OrbisNpMatching2TeamId teamId; @@ -146,129 +568,19 @@ struct OrbisNpMatching2CreateJoinRoomRequestA { }; static_assert(sizeof(OrbisNpMatching2CreateJoinRoomRequestA) == 184); -struct OrbisNpMatching2RoomDataInternal { - u16 publicSlots; - u16 privateSlots; - u16 openPublicSlots; - u16 openPrivateSlots; - u16 maxSlot; - OrbisNpMatching2ServerId serverId; - OrbisNpMatching2WorldId worldId; - OrbisNpMatching2LobbyId lobbyId; - OrbisNpMatching2RoomId roomId; - OrbisNpMatching2RoomPasswordSlotMask passwdSlotMask; - u64 joinedSlotMask; - OrbisNpMatching2RoomGroup* roomGroup; - u64 roomGroups; - OrbisNpMatching2Flags flags; - u8 pad[4]; - OrbisNpMatching2RoomBinAttrInternal* internalBinAttr; - u64 internalBinAttrs; -}; - -struct OrbisNpMatching2RoomMemberDataInternalA { - OrbisNpMatching2RoomMemberDataInternalA* next; - Libraries::Rtc::OrbisRtcTick joinDateTicks; - Libraries::Np::OrbisNpPeerAddressA user; - Libraries::Np::OrbisNpOnlineId onlineId; - u8 pad[4]; - OrbisNpMatching2RoomMemberId memberId; - OrbisNpMatching2TeamId teamId; - OrbisNpMatching2NatType natType; - OrbisNpMatching2Flags flags; - OrbisNpMatching2RoomGroup* roomGroup; - OrbisNpMatching2RoomMemberBinAttrInternal* roomMemberInternalBinAttr; - u64 roomMemberInternalBinAttrs; -}; - -struct OrbisNpMatching2RoomMemberDataInternalListA { - OrbisNpMatching2RoomMemberDataInternalA* members; - u64 membersNum; - OrbisNpMatching2RoomMemberDataInternalA* me; - OrbisNpMatching2RoomMemberDataInternalA* owner; +// CreateJoinRoom response +struct OrbisNpMatching2CreateJoinRoomResponse { + const OrbisNpMatching2RoomDataInternal* roomData; + OrbisNpMatching2RoomMemberDataInternalList members; }; +// CreateJoinRoom response (account-id variant) struct OrbisNpMatching2CreateJoinRoomResponseA { OrbisNpMatching2RoomDataInternal* roomData; OrbisNpMatching2RoomMemberDataInternalListA members; }; -struct OrbisNpMatching2GetWorldInfoListRequest { - OrbisNpMatching2ServerId serverId; -}; - -struct OrbisNpMatching2GetRoomDataInternalRequest { - OrbisNpMatching2RoomId roomId; - const OrbisNpMatching2AttributeId* attrId; - u64 attrIdNum; -}; - -struct OrbisNpMatching2World { - OrbisNpMatching2World* next; - OrbisNpMatching2WorldId worldId; - u32 lobbiesNum; - u32 maxLobbyMembersNum; - u32 lobbyMembersNum; - u32 roomsNum; - u32 roomMembersNum; - u8 pad[3]; -}; - -struct OrbisNpMatching2GetWorldInfoListResponse { - OrbisNpMatching2World* world; - u64 worldNum; -}; - -struct OrbisNpMatching2GroupLabel { - u8 data[8]; -}; - -struct OrbisNpMatching2SessionPassword { - u8 data[8]; -}; - -struct OrbisNpMatching2InitializeParameter { - u64 poolSize; - u64 unknown; - s32 priority; - u8 padding[4]; - u64 stackSize; - u64 size; - u64 sslPoolSize; -}; -static_assert(sizeof(OrbisNpMatching2InitializeParameter) == 0x30); - -struct OrbisNpMatching2PresenceOptionData { - u8 data[16]; - u64 len; -}; - -struct OrbisNpMatching2RoomMemberUpdateA { - OrbisNpMatching2RoomMemberDataInternalA* roomMemberDataInternal; - OrbisNpMatching2EventCause eventCause; - u8 padding[7]; - OrbisNpMatching2PresenceOptionData optData; -}; - -struct OrbisNpMatching2RoomUpdate { - OrbisNpMatching2EventCause eventCause; - u8 padding[3]; - s32 errorCode; - OrbisNpMatching2PresenceOptionData optData; -}; - -struct OrbisNpMatching2RoomDataInternalUpdate { - OrbisNpMatching2RoomDataInternal* chgRoomDataInternal; - OrbisNpMatching2FlagAttr* chgFlagAttr; - OrbisNpMatching2FlagAttr* prevFlagAttr; - OrbisNpMatching2RoomPasswordSlotMask* chgRoomPasswordSlotMask; - OrbisNpMatching2RoomPasswordSlotMask* prevRoomPasswordSlotMask; - OrbisNpMatching2RoomGroup** chgRoomGroup; - u64 chgRoomGroupNum; - OrbisNpMatching2RoomBinAttrInternal** chgRoomBinAttrInternal; - u64 chgRoomBinAttrInternalNum; -}; - +// JoinRoom request struct OrbisNpMatching2JoinRoomRequest { OrbisNpMatching2RoomId roomId; OrbisNpMatching2SessionPassword* roomPasswd; @@ -288,6 +600,7 @@ struct OrbisNpMatching2JoinRoomRequest { }; static_assert(sizeof(OrbisNpMatching2JoinRoomRequest) == 0x58); +// JoinRoom request (account-id variant) struct OrbisNpMatching2JoinRoomRequestA { OrbisNpMatching2RoomId roomId; OrbisNpMatching2SessionPassword* roomPasswd; @@ -307,6 +620,18 @@ struct OrbisNpMatching2JoinRoomRequestA { }; static_assert(sizeof(OrbisNpMatching2JoinRoomRequestA) == 0x58); +// LeaveRoom request +struct OrbisNpMatching2LeaveRoomRequest { + OrbisNpMatching2RoomId roomId; + OrbisNpMatching2PresenceOptionData optData; +}; + +// LeaveRoom response +struct OrbisNpMatching2LeaveRoomResponse { + OrbisNpMatching2RoomId roomId; +}; + +// KickoutRoomMember request struct OrbisNpMatching2KickoutRoomMemberRequest { OrbisNpMatching2RoomId roomId; OrbisNpMatching2RoomMemberId memberId; @@ -316,182 +641,7 @@ struct OrbisNpMatching2KickoutRoomMemberRequest { }; static_assert(sizeof(OrbisNpMatching2KickoutRoomMemberRequest) == 0x28); -struct OrbisNpMatching2LeaveRoomRequest { - OrbisNpMatching2RoomId roomId; - OrbisNpMatching2PresenceOptionData optData; -}; - -struct OrbisNpMatching2LeaveRoomResponse { - OrbisNpMatching2RoomId roomId; -}; - -struct OrbisNpMatching2Range { - u32 start; - u32 total; - u32 results; - u8 pad[4]; -}; - -struct OrbisNpMatching2RangeFilter { - u32 start; - u32 max; -}; - -using OrbisNpMatching2Operator = u8; - -struct OrbisNpMatching2IntSearchFilter { - OrbisNpMatching2Operator searchOperator; - u8 padding[7]; - OrbisNpMatching2IntAttr attr; -}; - -struct OrbisNpMatching2BinSearchFilter { - OrbisNpMatching2Operator searchOperator; - u8 padding[7]; - OrbisNpMatching2BinAttr attr; -}; - -struct OrbisNpMatching2RequestOptParam { - OrbisNpMatching2RequestCallback callback; - void* arg; - u32 timeout; - u16 appId; - u8 padding[2]; -}; - -struct OrbisNpMatching2RoomDataExternalA { - OrbisNpMatching2RoomDataExternalA* next; - u16 maxSlot; - u16 curMembers; - OrbisNpMatching2Flags flags; - OrbisNpMatching2ServerId serverId; - u8 pad[2]; - OrbisNpMatching2WorldId worldId; - OrbisNpMatching2LobbyId lobbyId; - OrbisNpMatching2RoomId roomId; - OrbisNpMatching2RoomPasswordSlotMask passwdSlotMask; - u64 joinedSlotMask; - u16 publicSlots; - u16 privateSlots; - u16 openPublicSlots; - u16 openPrivateSlots; - Libraries::Np::OrbisNpPeerAddressA owner; - Libraries::Np::OrbisNpOnlineId ownerOnlineId; - OrbisNpMatching2RoomGroupInfo* roomGroup; - u64 roomGroups; - OrbisNpMatching2IntAttr* externalSearchIntAttr; - u64 externalSearchIntAttrs; - OrbisNpMatching2BinAttr* externalSearchBinAttr; - u64 externalSearchBinAttrs; - OrbisNpMatching2BinAttr* externalBinAttr; - u64 externalBinAttrs; -}; - -struct OrbisNpMatching2RoomGroup { - OrbisNpMatching2RoomGroupId id; - bool hasPasswd; - bool hasLabel; - u8 pad; - OrbisNpMatching2GroupLabel label; - u32 slots; - u32 groupMembers; -}; - -struct OrbisNpMatching2RoomGroupConfig { - u32 slots; - bool hasLabel; - OrbisNpMatching2GroupLabel label; - bool hasPassword; - u8 pad[2]; -}; - -struct OrbisNpMatching2RoomGroupPasswordConfig { - OrbisNpMatching2RoomGroupId groupId; - bool hasPassword; - u8 pad[1]; -}; - -struct OrbisNpMatching2RoomGroupInfo { - OrbisNpMatching2RoomGroupId id; - bool hasPasswd; - u8 pad[2]; - u32 slots; - u32 groupMembers; -}; - -struct OrbisNpMatching2RoomBinAttrInternal { - Libraries::Rtc::OrbisRtcTick lastUpdate; - OrbisNpMatching2RoomMemberId memberId; - u8 pad[6]; - OrbisNpMatching2BinAttr binAttr; -}; - -struct OrbisNpMatching2RoomMemberBinAttrInternal { - Libraries::Rtc::OrbisRtcTick lastUpdate; - OrbisNpMatching2BinAttr binAttr; -}; - -struct OrbisNpMatching2RoomMemberDataInternal { - OrbisNpMatching2RoomMemberDataInternal* next; - u64 joinDate; - Libraries::Np::OrbisNpId npId; - u8 pad[4]; - OrbisNpMatching2RoomMemberId memberId; - OrbisNpMatching2TeamId teamId; - OrbisNpMatching2NatType natType; - OrbisNpMatching2Flags flagAttr; - OrbisNpMatching2RoomGroup* roomGroup; - OrbisNpMatching2RoomMemberBinAttrInternal* roomMemberBinAttrInternal; - u64 roomMemberBinAttrInternalNum; -}; -static_assert(sizeof(OrbisNpMatching2RoomMemberDataInternal) == 0x58); - -struct OrbisNpMatching2RoomMemberUpdate { - OrbisNpMatching2RoomMemberDataInternal* roomMemberDataInternal; - OrbisNpMatching2EventCause eventCause; - u8 padding[7]; - OrbisNpMatching2PresenceOptionData optData; -}; - -struct OrbisNpMatching2RoomMemberDataInternalList { - OrbisNpMatching2RoomMemberDataInternal* members; - u64 membersNum; - OrbisNpMatching2RoomMemberDataInternal* me; - OrbisNpMatching2RoomMemberDataInternal* owner; -}; - -struct OrbisNpMatching2CreateJoinRoomResponse { - const OrbisNpMatching2RoomDataInternal* roomData; - OrbisNpMatching2RoomMemberDataInternalList members; -}; - -struct OrbisNpMatching2RoomDataExternal { - OrbisNpMatching2RoomDataExternal* next; - u16 maxSlot; - u16 curMembers; - OrbisNpMatching2Flags flags; - OrbisNpMatching2ServerId serverId; - u8 pad[2]; - OrbisNpMatching2WorldId worldId; - OrbisNpMatching2LobbyId lobbyId; - OrbisNpMatching2RoomId roomId; - u64 passwdSlotMask; - u64 joinedSlotMask; - u16 publicSlots; - u16 privateSlots; - u16 openPublicSlots; - u16 openPrivateSlots; - Libraries::Np::OrbisNpId* ownerNpId; - OrbisNpMatching2RoomGroupInfo* roomGroup; - u64 roomGroups; - OrbisNpMatching2IntAttr* externalSearchIntAttr; - u64 externalSearchIntAttrs; - OrbisNpMatching2BinAttr* externalSearchBinAttr; - u64 externalSearchBinAttrs; - OrbisNpMatching2BinAttr* externalBinAttr; - u64 externalBinAttrs; -}; - +// SearchRoom request struct OrbisNpMatching2SearchRoomRequest { int option; OrbisNpMatching2WorldId worldId; @@ -507,16 +657,39 @@ struct OrbisNpMatching2SearchRoomRequest { u64 attrs; }; +// SearchRoom response struct OrbisNpMatching2SearchRoomResponse { OrbisNpMatching2Range range; OrbisNpMatching2RoomDataExternal* roomDataExt; }; +// SearchRoom response (account-id variant) struct OrbisNpMatching2SearchRoomResponseA { OrbisNpMatching2Range range; OrbisNpMatching2RoomDataExternalA* roomDataExt; }; +// GetRoomDataExternalList request +struct OrbisNpMatching2GetRoomDataExternalListRequest { + OrbisNpMatching2RoomId* roomId; + u64 roomIdNum; + const OrbisNpMatching2AttributeId* attrId; + u64 attrIdNum; +}; + +// GetRoomDataExternalList response +struct OrbisNpMatching2GetRoomDataExternalListResponse { + OrbisNpMatching2RoomDataExternal* roomDataExternal; + u64 roomDataExternalNum; +}; + +// GetRoomDataExternalList response (account-id variant) +struct OrbisNpMatching2GetRoomDataExternalListResponseA { + OrbisNpMatching2RoomDataExternalA* roomDataExternal; + u64 roomDataExternalNum; +}; + +// SetRoomDataExternal request struct OrbisNpMatching2SetRoomDataExternalRequest { OrbisNpMatching2RoomId roomId; const OrbisNpMatching2IntAttr* roomSearchableIntAttrExternal; @@ -527,6 +700,7 @@ struct OrbisNpMatching2SetRoomDataExternalRequest { u64 roomBinAttrExternalNum; }; +// SetRoomDataInternal request struct OrbisNpMatching2SetRoomDataInternalRequest { OrbisNpMatching2RoomId roomId; OrbisNpMatching2Flags flagFilter; @@ -540,6 +714,14 @@ struct OrbisNpMatching2SetRoomDataInternalRequest { u64 ownerPrivilegeRankNum; }; +// GetRoomDataInternal request +struct OrbisNpMatching2GetRoomDataInternalRequest { + OrbisNpMatching2RoomId roomId; + const OrbisNpMatching2AttributeId* attrId; + u64 attrIdNum; +}; + +// SetUserInfo request struct OrbisNpMatching2SetUserInfoRequest { OrbisNpMatching2ServerId serverId; u8 padding[6]; @@ -547,12 +729,51 @@ struct OrbisNpMatching2SetUserInfoRequest { u64 userBinAttrs; }; +// Room data internal update information +struct OrbisNpMatching2RoomDataInternalUpdate { + OrbisNpMatching2RoomDataInternal* chgRoomDataInternal; + OrbisNpMatching2FlagAttr* chgFlagAttr; + OrbisNpMatching2FlagAttr* prevFlagAttr; + OrbisNpMatching2RoomPasswordSlotMask* chgRoomPasswordSlotMask; + OrbisNpMatching2RoomPasswordSlotMask* prevRoomPasswordSlotMask; + OrbisNpMatching2RoomGroup** chgRoomGroup; + u64 chgRoomGroupNum; + OrbisNpMatching2RoomBinAttrInternal** chgRoomBinAttrInternal; + u64 chgRoomBinAttrInternalNum; +}; + +// Room update information +struct OrbisNpMatching2RoomUpdate { + OrbisNpMatching2EventCause eventCause; + u8 padding[3]; + s32 errorCode; + OrbisNpMatching2PresenceOptionData optData; +}; + +// Room member update information +struct OrbisNpMatching2RoomMemberUpdate { + OrbisNpMatching2RoomMemberDataInternal* roomMemberDataInternal; + OrbisNpMatching2EventCause eventCause; + u8 padding[7]; + OrbisNpMatching2PresenceOptionData optData; +}; + +// Room member update information (account-id variant) +struct OrbisNpMatching2RoomMemberUpdateA { + OrbisNpMatching2RoomMemberDataInternalA* roomMemberDataInternal; + OrbisNpMatching2EventCause eventCause; + u8 padding[7]; + OrbisNpMatching2PresenceOptionData optData; +}; + +// Signaling connection information address struct OrbisNpMatching2SignalingConnectionInfoAddr { u32 addr; u16 port; u8 pad[2]; }; +// Signaling connection information union OrbisNpMatching2SignalingConnectionInfo { u32 rtt; u32 bandwidth; @@ -562,6 +783,7 @@ union OrbisNpMatching2SignalingConnectionInfo { }; static_assert(sizeof(OrbisNpMatching2SignalingConnectionInfo) == 0x24); +// Signaling connection information (account-id variant) union OrbisNpMatching2SignalingConnectionInfoA { u32 rtt; u32 bandwidth; @@ -571,6 +793,7 @@ union OrbisNpMatching2SignalingConnectionInfoA { }; static_assert(sizeof(OrbisNpMatching2SignalingConnectionInfoA) == 0x10); +// SignalingGetPingInfo request struct OrbisNpMatching2SignalingGetPingInfoRequest { OrbisNpMatching2RoomId roomId; u8 pad[16]; @@ -580,6 +803,7 @@ struct OrbisNpMatching2SignalingGetPingInfoRequest { } }; +// SignalingGetPingInfo response struct OrbisNpMatching2SignalingGetPingInfoResponse { OrbisNpMatching2ServerId serverId; u8 pad[2]; @@ -590,6 +814,7 @@ struct OrbisNpMatching2SignalingGetPingInfoResponse { }; static_assert(sizeof(OrbisNpMatching2SignalingGetPingInfoResponse) == 0x28); +// Signaling parameter struct OrbisNpMatching2SignalingParam { int type; int flag; @@ -598,3 +823,76 @@ struct OrbisNpMatching2SignalingParam { }; } // namespace Libraries::Np::NpMatching2 + +namespace Libraries::Np::NpSignaling { + +using OrbisNpSignalingContextId = s32; +using OrbisNpSignalingConnectionId = s32; +using OrbisNpSignalingRequestId = u32; + +// Signaling handler callback function +using OrbisNpSignalingHandler = PS4_SYSV_ABI void (*)(u32 ctxId, u32 connId, s32 event, + s32 errorCode, void* userArg); + +// Signaling event +constexpr s32 ORBIS_NP_SIGNALING_EVENT_DEAD = 0; +constexpr s32 ORBIS_NP_SIGNALING_EVENT_ESTABLISHED = 1; +constexpr s32 ORBIS_NP_SIGNALING_EVENT_NETINFO_ERROR = 2; +constexpr s32 ORBIS_NP_SIGNALING_EVENT_NETINFO_RESULT = 3; +constexpr s32 ORBIS_NP_SIGNALING_EVENT_PEER_ACTIVATED = 10; +constexpr s32 ORBIS_NP_SIGNALING_EVENT_PEER_DEACTIVATED = 11; +constexpr s32 ORBIS_NP_SIGNALING_EVENT_MUTUAL_ACTIVATED = 12; + +// Connection status +constexpr s32 ORBIS_NP_SIGNALING_CONN_STATUS_INACTIVE = 0; +constexpr s32 ORBIS_NP_SIGNALING_CONN_STATUS_PENDING = 1; +constexpr s32 ORBIS_NP_SIGNALING_CONN_STATUS_ACTIVE = 2; + +// Type of connection information to acquire +constexpr s32 ORBIS_NP_SIGNALING_CONN_INFO_RTT = 1; +constexpr s32 ORBIS_NP_SIGNALING_CONN_INFO_BANDWIDTH = 2; +constexpr s32 ORBIS_NP_SIGNALING_CONN_INFO_PEER_NP_ID = 3; +constexpr s32 ORBIS_NP_SIGNALING_CONN_INFO_PEER_ADDR = 4; +constexpr s32 ORBIS_NP_SIGNALING_CONN_INFO_MAPPED_ADDR = 5; +constexpr s32 ORBIS_NP_SIGNALING_CONN_INFO_PACKET_LOSS = 6; +constexpr s32 ORBIS_NP_SIGNALING_CONN_INFO_PEER_ADDRESS_A = 7; + +// Context option +constexpr s32 ORBIS_NP_SIGNALING_CONTEXT_OPTION_FLAG = 1; + +// Network information +struct OrbisNpSignalingNetInfo { + u64 size; + u32 localAddr; + u32 mappedAddr; + s32 natStatus; + u32 _pad_14; +}; +static_assert(sizeof(OrbisNpSignalingNetInfo) == 0x18); + +// Account-id / platform pair +struct OrbisNpSignalingAccountPlatformPair { + u64 accountId; + u32 platformType; + u32 _pad_0c; +}; +static_assert(sizeof(OrbisNpSignalingAccountPlatformPair) == 0x10); + +// Memory information +struct OrbisNpSignalingMemoryInfo { + u64 currentInUse; + u64 peakInUse; + u64 maxSystemSize; +}; +static_assert(sizeof(OrbisNpSignalingMemoryInfo) == 0x18); + +// Connection statistics +struct OrbisNpSignalingConnectionStatistics { + u32 peakConnectionCount; + u32 activeConnectionCount; + u32 transientConnectionCount; + u32 establishedConnectionCount; +}; +static_assert(sizeof(OrbisNpSignalingConnectionStatistics) == 0x10); + +} // namespace Libraries::Np::NpSignaling diff --git a/src/shadnet/shadnet.proto b/src/shadnet/shadnet.proto index 8ffcaaa7e..71b3f7c68 100644 --- a/src/shadnet/shadnet.proto +++ b/src/shadnet/shadnet.proto @@ -279,6 +279,8 @@ message MatchingRoomDataExternal { repeated MatchingBinAttr external_search_bin_attrs = 16; repeated MatchingBinAttr external_bin_attrs = 17; string owner_npid = 18; + uint64 owner_account_id = 19; + uint32 owner_platform = 20; } message CreateJoinRoomResponse { @@ -433,6 +435,15 @@ message SearchRoomReply { uint32 range_result = 4; } +message GetRoomDataExternalListRequest { + repeated uint64 room_ids = 1; + repeated uint32 attr_ids = 2; +} + +message GetRoomDataExternalListReply { + repeated MatchingRoomDataExternal rooms = 1; +} + message MatchingWorld { uint32 world_id = 1; uint32 lobbies_num = 2;