diff --git a/rpcs3/Emu/CMakeLists.txt b/rpcs3/Emu/CMakeLists.txt index b72f99d9d7..a954b9e67e 100644 --- a/rpcs3/Emu/CMakeLists.txt +++ b/rpcs3/Emu/CMakeLists.txt @@ -375,7 +375,9 @@ target_sources(rpcs3_emu PRIVATE # Np target_sources(rpcs3_emu PRIVATE NP/fb_helpers.cpp + NP/np_cache.cpp NP/np_contexts.cpp + NP/np_dnshook.cpp NP/np_handler.cpp NP/np_helpers.cpp NP/np_notifications.cpp diff --git a/rpcs3/Emu/Cell/Modules/sceNp.cpp b/rpcs3/Emu/Cell/Modules/sceNp.cpp index bb1518307a..02ee3444c9 100644 --- a/rpcs3/Emu/Cell/Modules/sceNp.cpp +++ b/rpcs3/Emu/Cell/Modules/sceNp.cpp @@ -680,7 +680,7 @@ error_code sceNpBasicRegisterHandler(vm::cptr context, vm: error_code sceNpBasicRegisterContextSensitiveHandler(vm::cptr context, vm::ptr handler, vm::ptr arg) { - sceNp.todo("sceNpBasicRegisterContextSensitiveHandler(context=*0x%x, handler=*0x%x, arg=*0x%x)", context, handler, arg); + sceNp.notice("sceNpBasicRegisterContextSensitiveHandler(context=*0x%x, handler=*0x%x, arg=*0x%x)", context, handler, arg); auto& nph = g_fxo->get>(); diff --git a/rpcs3/Emu/Cell/Modules/sceNp2.cpp b/rpcs3/Emu/Cell/Modules/sceNp2.cpp index 2a15501626..2d393c7bb5 100644 --- a/rpcs3/Emu/Cell/Modules/sceNp2.cpp +++ b/rpcs3/Emu/Cell/Modules/sceNp2.cpp @@ -755,7 +755,7 @@ error_code sceNpMatching2GetEventData(SceNpMatching2ContextId ctxId, SceNpMatchi error_code sceNpMatching2GetRoomSlotInfoLocal(SceNpMatching2ContextId ctxId, const SceNpMatching2RoomId roomId, vm::ptr roomSlotInfo) { - sceNp2.todo("sceNpMatching2GetRoomSlotInfoLocal(ctxId=%d, roomId=%d, roomSlotInfo=*0x%x)", ctxId, roomId, roomSlotInfo); + sceNp2.notice("sceNpMatching2GetRoomSlotInfoLocal(ctxId=%d, roomId=%d, roomSlotInfo=*0x%x)", ctxId, roomId, roomSlotInfo); auto& nph = g_fxo->get>(); @@ -764,6 +764,30 @@ error_code sceNpMatching2GetRoomSlotInfoLocal(SceNpMatching2ContextId ctxId, con return SCE_NP_MATCHING2_ERROR_NOT_INITIALIZED; } + if (!ctxId) + { + return SCE_NP_MATCHING2_ERROR_INVALID_CONTEXT_ID; + } + + if (!roomId) + { + return SCE_NP_MATCHING2_ERROR_INVALID_ROOM_ID; + } + + if (!check_match2_context(ctxId)) + { + return SCE_NP_MATCHING2_ERROR_CONTEXT_NOT_FOUND; + } + + const auto [error, slots] = nph.local_get_room_slots(roomId); + + if (error) + { + return error; + } + + memcpy(roomSlotInfo.get_ptr(), &slots.value(), sizeof(SceNpMatching2RoomSlotInfo)); + return CELL_OK; } @@ -797,7 +821,7 @@ error_code sceNpMatching2AbortContextStart(SceNpMatching2ContextId ctxId) error_code sceNpMatching2GetRoomMemberIdListLocal(SceNpMatching2ContextId ctxId, SceNpMatching2RoomId roomId, s32 sortMethod, vm::ptr memberId, u32 memberIdNum) { - sceNp2.todo("sceNpMatching2GetRoomMemberIdListLocal(ctxId=%d, roomId=%d, sortMethod=%d, memberId=*0x%x, memberIdNum=%d)", ctxId, roomId, sortMethod, memberId, memberIdNum); + sceNp2.notice("sceNpMatching2GetRoomMemberIdListLocal(ctxId=%d, roomId=%d, sortMethod=%d, memberId=*0x%x, memberIdNum=%d)", ctxId, roomId, sortMethod, memberId, memberIdNum); auto& nph = g_fxo->get>(); @@ -806,7 +830,41 @@ error_code sceNpMatching2GetRoomMemberIdListLocal(SceNpMatching2ContextId ctxId, return SCE_NP_MATCHING2_ERROR_NOT_INITIALIZED; } - return CELL_OK; + if (!ctxId) + { + return SCE_NP_MATCHING2_ERROR_INVALID_CONTEXT_ID; + } + + if (!roomId) + { + return SCE_NP_MATCHING2_ERROR_INVALID_ROOM_ID; + } + + if (sortMethod != SCE_NP_MATCHING2_SORT_METHOD_JOIN_DATE && sortMethod != SCE_NP_MATCHING2_SORT_METHOD_SLOT_NUMBER) + { + return SCE_NP_MATCHING2_ERROR_INVALID_SORT_METHOD; + } + + if (!check_match2_context(ctxId)) + { + return SCE_NP_MATCHING2_ERROR_CONTEXT_NOT_FOUND; + } + + const auto [error, vec_memberids] = nph.local_get_room_memberids(roomId, sortMethod); + + if (error) + { + return error; + } + + u32 num_members = std::min(memberIdNum, static_cast(vec_memberids.size())); + + for (u32 i = 0; i < num_members; i++) + { + memberId[i] = vec_memberids[i]; + } + + return not_an_error(num_members); } error_code sceNpMatching2JoinRoom( @@ -826,10 +884,10 @@ error_code sceNpMatching2JoinRoom( } error_code sceNpMatching2GetRoomMemberDataInternalLocal(SceNpMatching2ContextId ctxId, SceNpMatching2RoomId roomId, SceNpMatching2RoomMemberId memberId, vm::cptr attrId, - u32 attrIdNum, vm::ptr member, vm::ptr buf, u64 bufLen) + u32 attrIdNum, vm::ptr member, vm::ptr buf, u64 bufLen) { - sceNp2.todo("sceNpMatching2GetRoomMemberDataInternalLocal(ctxId=%d, roomId=%d, memberId=%d, attrId=*0x%x, attrIdNum=%d, member=*0x%x, buf=*0x%x, bufLen=%d)", ctxId, roomId, memberId, attrId, - attrIdNum, member, buf, bufLen); + sceNp2.warning("sceNpMatching2GetRoomMemberDataInternalLocal(ctxId=%d, roomId=%d, memberId=%d, attrId=*0x%x, attrIdNum=%d, member=*0x%x, buf=*0x%x, bufLen=%d)", ctxId, roomId, memberId, attrId, + attrIdNum, member, buf, bufLen); auto& nph = g_fxo->get>(); @@ -838,7 +896,37 @@ error_code sceNpMatching2GetRoomMemberDataInternalLocal(SceNpMatching2ContextId return SCE_NP_MATCHING2_ERROR_NOT_INITIALIZED; } - return CELL_OK; + if (!ctxId) + { + return SCE_NP_MATCHING2_ERROR_INVALID_CONTEXT_ID; + } + + if (!roomId) + { + return SCE_NP_MATCHING2_ERROR_INVALID_ROOM_ID; + } + + if (!memberId) + { + return SCE_NP_MATCHING2_ERROR_INVALID_MEMBER_ID; + } + + std::vector binattrs_list; + for (u32 i = 0; i < attrIdNum; i++) + { + if (attrId[i] < SCE_NP_MATCHING2_ROOMMEMBER_BIN_ATTR_INTERNAL_1_ID || attrId[i] >= SCE_NP_MATCHING2_USER_BIN_ATTR_1_ID) + { + return SCE_NP_MATCHING2_ERROR_INVALID_ATTRIBUTE_ID; + } + binattrs_list.push_back(attrId[i]); + } + + if (!check_match2_context(ctxId)) + { + return SCE_NP_MATCHING2_ERROR_CONTEXT_NOT_FOUND; + } + + return nph.local_get_room_member_data(roomId, memberId, binattrs_list, member ? member.get_ptr() : nullptr, buf.addr(), bufLen); } error_code sceNpMatching2GetCbQueueInfo(SceNpMatching2ContextId ctxId, vm::ptr queueInfo) @@ -1005,7 +1093,7 @@ error_code sceNpMatching2SignalingGetPingInfo( error_code sceNpMatching2GetServerIdListLocal(SceNpMatching2ContextId ctxId, vm::ptr serverId, u32 serverIdNum) { - sceNp2.todo("sceNpMatching2GetServerIdListLocal(ctxId=%d, serverId=*0x%x, serverIdNum=%d)", ctxId, serverId, serverIdNum); + sceNp2.notice("sceNpMatching2GetServerIdListLocal(ctxId=%d, serverId=*0x%x, serverIdNum=%d)", ctxId, serverId, serverIdNum); auto& nph = g_fxo->get>(); @@ -1267,7 +1355,7 @@ error_code sceNpMatching2RegisterRoomEventCallback(SceNpMatching2ContextId ctxId error_code sceNpMatching2GetRoomPasswordLocal(SceNpMatching2ContextId ctxId, SceNpMatching2RoomId roomId, vm::ptr withPassword, vm::ptr roomPassword) { - sceNp2.todo("sceNpMatching2GetRoomPasswordLocal(ctxId=%d, roomId=%d, withPassword=*0x%x, roomPassword=*0x%x)", ctxId, roomId, withPassword, roomPassword); + sceNp2.notice("sceNpMatching2GetRoomPasswordLocal(ctxId=%d, roomId=%d, withPassword=*0x%x, roomPassword=*0x%x)", ctxId, roomId, withPassword, roomPassword); auto& nph = g_fxo->get>(); @@ -1276,6 +1364,38 @@ error_code sceNpMatching2GetRoomPasswordLocal(SceNpMatching2ContextId ctxId, Sce return SCE_NP_MATCHING2_ERROR_NOT_INITIALIZED; } + if (!ctxId) + { + return SCE_NP_MATCHING2_ERROR_INVALID_CONTEXT_ID; + } + + if (!roomId) + { + return SCE_NP_MATCHING2_ERROR_INVALID_ROOM_ID; + } + + if (!check_match2_context(ctxId)) + { + return SCE_NP_MATCHING2_ERROR_CONTEXT_NOT_FOUND; + } + + const auto [error, password] = nph.local_get_room_password(roomId); + + if (error) + { + return error; + } + + if (password) + { + *withPassword = true; + memcpy(roomPassword.get_ptr(), &*password, sizeof(SceNpMatching2SessionPassword)); + } + else + { + *withPassword = false; + } + return CELL_OK; } diff --git a/rpcs3/Emu/Cell/lv2/sys_net.cpp b/rpcs3/Emu/Cell/lv2/sys_net.cpp index b6cc8270da..fa2b2b9279 100644 --- a/rpcs3/Emu/Cell/lv2/sys_net.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_net.cpp @@ -24,6 +24,7 @@ #endif #include "Emu/NP/np_handler.h" +#include "Emu/NP/np_dnshook.h" #include #include @@ -1695,6 +1696,7 @@ error_code sys_net_bnet_connect(ppu_thread& ppu, s32 s, vm::ptrsin_port == 53) { + auto& dnshook = g_fxo->get(); auto& nph = g_fxo->get>(); // Hack for DNS @@ -1703,7 +1705,7 @@ error_code sys_net_bnet_connect(ppu_thread& ppu, s32 s, vm::ptrsa_family != SYS_NET_AF_INET) { @@ -2286,10 +2288,12 @@ error_code sys_net_bnet_recvfrom(ppu_thread& ppu, s32 s, vm::ptr buf, u32 //if (!(sock.events & lv2_socket::poll::read)) { - auto& nph = g_fxo->get>(); - if (nph.is_dns(s) && nph.is_dns_queue(s)) + auto& dnshook = g_fxo->get(); + if (dnshook.is_dns(s) && dnshook.is_dns_queue(s)) { - const auto packet = nph.get_dns_packet(s); + auto& nph = g_fxo->get>(); + + const auto packet = dnshook.get_dns_packet(s); ensure(packet.size() < len); memcpy(buf.get_ptr(), packet.data(), packet.size()); @@ -2708,17 +2712,18 @@ error_code sys_net_bnet_sendto(ppu_thread& ppu, s32 s, vm::cptr buf, u32 l //if (!(sock.events & lv2_socket::poll::write)) { - auto& nph = g_fxo->get>(); + auto& dnshook = g_fxo->get(); if (addr && type == SYS_NET_SOCK_DGRAM && psa_in->sin_port == 53) { - nph.add_dns_spy(s); + dnshook.add_dns_spy(s); } - if (nph.is_dns(s)) + if (dnshook.is_dns(s)) { - const s32 ret_analyzer = nph.analyze_dns_packet(s, reinterpret_cast(_buf.data()), len); + const s32 ret_analyzer = dnshook.analyze_dns_packet(s, reinterpret_cast(_buf.data()), len); // If we're not connected just never send the packet and pretend we did + auto& nph = g_fxo->get>(); if (!nph.get_net_status()) { native_result = data_len; @@ -3217,8 +3222,8 @@ error_code sys_net_bnet_close(ppu_thread& ppu, s32 s) } } - auto& nph = g_fxo->get>(); - nph.remove_dns_spy(s); + auto& dnshook = g_fxo->get(); + dnshook.remove_dns_spy(s); return CELL_OK; } @@ -3309,8 +3314,8 @@ error_code sys_net_bnet_poll(ppu_thread& ppu, vm::ptr fds, s32 n else { // Check for fake packet for dns interceptions - auto& nph = g_fxo->get>(); - if (fds_buf[i].events & SYS_NET_POLLIN && nph.is_dns(fds_buf[i].fd) && nph.is_dns_queue(fds_buf[i].fd)) + auto& dnshook = g_fxo->get(); + if (fds_buf[i].events & SYS_NET_POLLIN && dnshook.is_dns(fds_buf[i].fd) && dnshook.is_dns_queue(fds_buf[i].fd)) fds_buf[i].revents |= SYS_NET_POLLIN; if (fds_buf[i].events & ~(SYS_NET_POLLIN | SYS_NET_POLLOUT | SYS_NET_POLLERR)) diff --git a/rpcs3/Emu/NP/fb_helpers.cpp b/rpcs3/Emu/NP/fb_helpers.cpp index 1b54da9742..c6feee14c1 100644 --- a/rpcs3/Emu/NP/fb_helpers.cpp +++ b/rpcs3/Emu/NP/fb_helpers.cpp @@ -182,14 +182,13 @@ namespace np u16 np_handler::RoomDataInternal_to_SceNpMatching2RoomDataInternal(event_data& edata, const RoomDataInternal* resp, SceNpMatching2RoomDataInternal* room_info, const SceNpId& npid) { - u16 member_id = 0; - room_info->serverId = resp->serverId(); - room_info->worldId = resp->worldId(); - room_info->lobbyId = resp->lobbyId(); - room_info->roomId = resp->roomId(); - room_info->passwordSlotMask = resp->passwordSlotMask(); - room_info->maxSlot = resp->maxSlot(); - room_info->memberList.membersNum = resp->memberList()->size(); + u16 member_id = 0; + room_info->serverId = resp->serverId(); + room_info->worldId = resp->worldId(); + room_info->lobbyId = resp->lobbyId(); + room_info->roomId = resp->roomId(); + room_info->passwordSlotMask = resp->passwordSlotMask(); + room_info->maxSlot = resp->maxSlot(); if (resp->roomGroup() && resp->roomGroup()->size() != 0) { @@ -199,32 +198,43 @@ namespace np } room_info->memberList.membersNum = static_cast(resp->memberList()->size()); + edata.allocate(sizeof(SceNpMatching2RoomMemberDataInternal) * room_info->memberList.membersNum, room_info->memberList.members); - SceNpMatching2RoomMemberDataInternal* prev_member = nullptr; for (flatbuffers::uoffset_t i = 0; i < resp->memberList()->size(); i++) { - auto fb_member = resp->memberList()->Get(i); - SceNpMatching2RoomMemberDataInternal* member_info; + auto fb_member = resp->memberList()->Get(i); + SceNpMatching2RoomMemberDataInternal* sce_member = &room_info->memberList.members[i]; - member_info = (i > 0) ? edata.allocate(sizeof(SceNpMatching2RoomMemberDataInternal), prev_member->next) : - edata.allocate(sizeof(SceNpMatching2RoomMemberDataInternal), room_info->memberList.members); - - RoomMemberDataInternal_to_SceNpMatching2RoomMemberDataInternal(edata, fb_member, room_info, member_info); - - if (strcmp(member_info->userInfo.npId.handle.data, npid.handle.data) == 0) + if (i < (resp->memberList()->size() - 1)) { - room_info->memberList.me = (i > 0) ? prev_member->next : room_info->memberList.members; + sce_member->next = room_info->memberList.members + i + 1; + edata.add_relocation(sce_member->next); + } + + RoomMemberDataInternal_to_SceNpMatching2RoomMemberDataInternal(edata, fb_member, room_info, sce_member); + } + + for (u32 i = 0; i < room_info->memberList.membersNum; i++) + { + SceNpMatching2RoomMemberDataInternal* sce_member = &room_info->memberList.members[i]; + if (strcmp(sce_member->userInfo.npId.handle.data, npid.handle.data) == 0) + { + room_info->memberList.me = room_info->memberList.members + i; edata.add_relocation(room_info->memberList.me); - member_id = member_info->memberId; + member_id = sce_member->memberId; + break; } + } - if (member_info->memberId == resp->ownerId()) + for (u32 i = 0; i < room_info->memberList.membersNum; i++) + { + SceNpMatching2RoomMemberDataInternal* sce_member = &room_info->memberList.members[i]; + if (sce_member->memberId == resp->ownerId()) { - room_info->memberList.owner = (i > 0) ? prev_member->next : room_info->memberList.members; + room_info->memberList.owner = room_info->memberList.members + i; edata.add_relocation(room_info->memberList.owner); + break; } - - prev_member = member_info; } room_info->flagAttr = resp->flagAttr(); @@ -375,7 +385,7 @@ namespace np { if (ret_ptr->data.id == binattr_id) return ret_ptr; - + ret_ptr++; } rpcn_log.fatal("RoomDataInternalUpdateInfo_to_SceNpMatching2RoomDataInternalUpdateInfo: Couldn't find matching roomBinAttrInternal!"); @@ -391,7 +401,7 @@ namespace np } } - void np_handler::RoomMemberDataInternalUpdateInfo_to_SceNpMatching2RoomMemberDataInternalUpdateInfo(event_data &edata, const RoomMemberDataInternalUpdateInfo* update_info, SceNpMatching2RoomMemberDataInternalUpdateInfo* sce_update_info) + void np_handler::RoomMemberDataInternalUpdateInfo_to_SceNpMatching2RoomMemberDataInternalUpdateInfo(event_data& edata, const RoomMemberDataInternalUpdateInfo* update_info, SceNpMatching2RoomMemberDataInternalUpdateInfo* sce_update_info) { auto* sce_room_member_data = edata.allocate(sizeof(SceNpMatching2RoomMemberDataInternal), sce_update_info->newRoomMemberDataInternal); RoomMemberDataInternal_to_SceNpMatching2RoomMemberDataInternal(edata, update_info->newRoomMemberDataInternal(), nullptr, sce_room_member_data); @@ -419,7 +429,7 @@ namespace np { if (ret_ptr->data.id == binattr_id) return ret_ptr; - + ret_ptr++; } rpcn_log.fatal("RoomMemberDataInternalUpdateInfo_to_SceNpMatching2RoomMemberDataInternalUpdateInfo: Couldn't find matching roomMemberBinAttrInternal!"); @@ -479,8 +489,8 @@ namespace np if (auto msg = mi->msg()) { - sce_mi->msgLen = msg->size(); - auto* ptr_msg_data = static_cast(edata.allocate(msg->size(), sce_mi->msg)); + sce_mi->msgLen = msg->size(); + auto* ptr_msg_data = static_cast(edata.allocate(msg->size(), sce_mi->msg)); for (u32 i = 0; i < msg->size(); i++) { ptr_msg_data[i] = msg->Get(i); diff --git a/rpcs3/Emu/NP/np_allocator.h b/rpcs3/Emu/NP/np_allocator.h index 44e3936ef4..80808fb3e8 100644 --- a/rpcs3/Emu/NP/np_allocator.h +++ b/rpcs3/Emu/NP/np_allocator.h @@ -88,11 +88,14 @@ namespace np void free(u32 addr) { + std::lock_guard lock(m_mutex); + ensure(addr >= m_pool.addr() && addr < (m_pool.addr() + m_size), "memory_allocator::free: addr is out of bounds!"); const u32 offset = addr - m_pool.addr(); ensure(m_allocs.contains(offset), "memory_allocator::free: m_allocs doesn't contain the allocation!"); + m_avail += m_allocs.at(offset); m_allocs.erase(offset); } @@ -106,6 +109,7 @@ namespace np ensure(m_allocs.contains(offset), "memory_allocator::reduce_allocation: m_allocs doesn't contain the allocation!"); ensure(m_allocs[offset] >= new_size, "memory_allocator::reduce_allocation: New size is bigger than current allocation!"); + m_avail += (m_allocs.at(offset) - new_size); m_allocs[offset] = new_size; } diff --git a/rpcs3/Emu/NP/np_cache.cpp b/rpcs3/Emu/NP/np_cache.cpp new file mode 100644 index 0000000000..18fb2f7134 --- /dev/null +++ b/rpcs3/Emu/NP/np_cache.cpp @@ -0,0 +1,302 @@ +#include "stdafx.h" +#include + +#include "np_allocator.h" +#include "np_cache.h" + +namespace np +{ + memberbin_cache::memberbin_cache(SceNpMatching2RoomMemberBinAttrInternal* sce_memberbin) + { + id = sce_memberbin->data.id; + updateDate.tick = sce_memberbin->updateDate.tick; + data.resize(sce_memberbin->data.size); + memcpy(data.data(), sce_memberbin->data.ptr.get_ptr(), sce_memberbin->data.size); + } + + member_cache::member_cache(const SceNpMatching2RoomMemberDataInternal* sce_member) + { + userInfo.npId = sce_member->userInfo.npId; + if (sce_member->userInfo.onlineName) + { + userInfo.onlineName = *sce_member->userInfo.onlineName; + } + if (sce_member->userInfo.avatarUrl) + { + userInfo.avatarUrl = *sce_member->userInfo.avatarUrl; + } + + joinDate.tick = sce_member->joinDate.tick; + memberId = sce_member->memberId; + teamId = sce_member->teamId; + if (sce_member->roomGroup) + { + group_id = sce_member->roomGroup->groupId; + } + else + { + group_id = 0; + } + + natType = sce_member->natType; + flagAttr = sce_member->flagAttr; + + for (u32 i = 0; i < sce_member->roomMemberBinAttrInternalNum; i++) + { + bins.insert_or_assign(sce_member->roomMemberBinAttrInternal[i].data.id, memberbin_cache(&sce_member->roomMemberBinAttrInternal[i])); + } + } + + void room_cache::update(const SceNpMatching2RoomDataInternal* sce_roomdata) + { + num_slots = sce_roomdata->maxSlot; + mask_password = sce_roomdata->passwordSlotMask; + + groups.clear(); + for (u32 i = 0; i < sce_roomdata->roomGroupNum; i++) + { + const SceNpMatching2RoomGroup* sce_group = &sce_roomdata->roomGroup[i]; + memcpy(&groups[sce_group->groupId], sce_group, sizeof(SceNpMatching2RoomGroup)); + } + + members.clear(); + vm::bptr sce_member = sce_roomdata->memberList.members; + while (sce_member) + { + members.insert_or_assign(sce_member->memberId, member_cache(sce_member.get_ptr())); + sce_member = sce_member->next; + } + + if (sce_roomdata->memberList.me == sce_roomdata->memberList.owner) + { + owner = true; + } + } + + void cache_manager::insert_room(const SceNpMatching2RoomDataInternal* sce_roomdata) + { + std::lock_guard lock(mutex); + + rooms[sce_roomdata->roomId].update(sce_roomdata); + } + + void cache_manager::add_member(SceNpMatching2RoomId room_id, const SceNpMatching2RoomMemberDataInternal* sce_roommemberdata) + { + std::lock_guard lock(mutex); + + ensure(rooms.contains(room_id), "cache_manager::add_member: Room not cached!"); + rooms[room_id].members.insert_or_assign(sce_roommemberdata->memberId, member_cache(sce_roommemberdata)); + } + + void cache_manager::del_member(SceNpMatching2RoomId room_id, SceNpMatching2RoomMemberId member_id) + { + std::lock_guard lock(mutex); + + ensure(rooms.contains(room_id), "cache_manager::del_member: Room not cached!"); + rooms.erase(member_id); + } + + void cache_manager::update_password(SceNpMatching2RoomId room_id, const std::optional& password) + { + std::lock_guard lock(mutex); + + rooms[room_id].password = password; + } + + std::pair> cache_manager::get_slots(SceNpMatching2RoomId room_id) + { + std::lock_guard lock(mutex); + + if (!rooms.contains(room_id)) + { + return {SCE_NP_MATCHING2_ERROR_ROOM_NOT_FOUND, {}}; + } + + const auto& room = rooms[room_id]; + + SceNpMatching2RoomSlotInfo slots; + + slots.roomId = room_id; + + SceNpMatching2RoomJoinedSlotMask join_mask = 0; + for (const auto& member : room.members) + { + join_mask |= (1 << (member.first - 1)); + } + slots.joinedSlotMask = join_mask; + slots.passwordSlotMask = room.mask_password; + + u64 joinable_slot_mask = (static_cast(1) << room.num_slots) - 1; + u16 num_private_slots = std::popcount(room.mask_password & joinable_slot_mask); + u16 num_public_slots = room.num_slots - num_private_slots; + + slots.publicSlotNum = num_public_slots; + slots.privateSlotNum = num_private_slots; + + u16 open_private_slots = num_private_slots - std::popcount(join_mask & room.mask_password); + u16 open_public_slots = num_public_slots - std::popcount(join_mask & (~room.mask_password)); + + slots.openPublicSlotNum = open_public_slots; + slots.openPrivateSlotNum = open_private_slots; + + return {CELL_OK, slots}; + } + + std::pair> cache_manager::get_memberids(u64 room_id, s32 sort_method) + { + std::lock_guard lock(mutex); + + if (!rooms.contains(room_id)) + { + return {SCE_NP_MATCHING2_ERROR_ROOM_NOT_FOUND, {}}; + } + + const auto& room = rooms[room_id]; + + std::vector vec_memberids; + + switch (sort_method) + { + case SCE_NP_MATCHING2_SORT_METHOD_SLOT_NUMBER: + { + for (const auto& member : room.members) + { + vec_memberids.push_back(member.first); + } + break; + } + case SCE_NP_MATCHING2_SORT_METHOD_JOIN_DATE: + { + std::map map_joindate_id; + + for (const auto& member : room.members) + { + map_joindate_id.insert(std::make_pair(member.second.joinDate.tick, member.first)); + } + + for (const auto& member : map_joindate_id) + { + vec_memberids.push_back(member.second); + } + + break; + } + default: fmt::throw_exception("Unreachable"); + } + + return {CELL_OK, vec_memberids}; + } + + std::pair> cache_manager::get_password(SceNpMatching2RoomId room_id) + { + std::lock_guard lock(mutex); + + if (!rooms.contains(room_id)) + { + return {SCE_NP_MATCHING2_ERROR_ROOM_NOT_FOUND, {}}; + } + + if (!rooms[room_id].owner) + { + return {SCE_NP_MATCHING2_ERROR_NOT_ALLOWED, {}}; + } + + return {CELL_OK, rooms[room_id].password}; + } + + error_code cache_manager::get_member_and_attrs(SceNpMatching2RoomId room_id, SceNpMatching2RoomMemberId member_id, const std::vector& binattrs_list, SceNpMatching2RoomMemberDataInternal* ptr_member, u32 addr_data, u32 size_data) + { + std::lock_guard lock(mutex); + + if (!rooms.contains(room_id)) + { + return SCE_NP_MATCHING2_ERROR_ROOM_NOT_FOUND; + } + + if (!rooms[room_id].members.contains(member_id)) + { + return SCE_NP_MATCHING2_ERROR_ROOM_MEMBER_NOT_FOUND; + } + + const auto& room = rooms.at(room_id); + const auto& member = room.members.at(member_id); + + if (ptr_member) + { + memset(ptr_member, 0, sizeof(SceNpMatching2RoomMemberDataInternal)); + memcpy(&ptr_member->userInfo.npId, &member.userInfo.npId, sizeof(SceNpId)); + ptr_member->joinDate.tick = member.joinDate.tick; + ptr_member->memberId = member.memberId; + ptr_member->teamId = member.teamId; + ptr_member->natType = member.natType; + ptr_member->flagAttr = member.flagAttr; + } + + const u32 needed_data_size = sizeof(SceNpOnlineName) + sizeof(SceNpAvatarUrl) + sizeof(SceNpMatching2RoomGroup) + + (binattrs_list.size() * (sizeof(SceNpMatching2RoomMemberBinAttrInternal) + SCE_NP_MATCHING2_ROOMMEMBER_BIN_ATTR_INTERNAL_MAX_SIZE)); + + if (!addr_data || !ptr_member) + { + return needed_data_size; + } + + if (size_data < needed_data_size) + { + return SCE_NP_MATCHING2_ERROR_INSUFFICIENT_BUFFER; + } + + memory_allocator mem; + mem.setup(vm::ptr(vm::cast(addr_data)), size_data); + + if (member.userInfo.onlineName) + { + ptr_member->userInfo.onlineName.set(mem.allocate(sizeof(SceNpOnlineName))); + memcpy(ptr_member->userInfo.onlineName.get_ptr(), &member.userInfo.onlineName.value(), sizeof(SceNpOnlineName)); + } + + if (member.userInfo.avatarUrl) + { + ptr_member->userInfo.avatarUrl.set(mem.allocate(sizeof(SceNpAvatarUrl))); + memcpy(ptr_member->userInfo.avatarUrl.get_ptr(), &member.userInfo.avatarUrl.value(), sizeof(SceNpAvatarUrl)); + } + + if (member.group_id) + { + ptr_member->roomGroup.set(mem.allocate(sizeof(SceNpMatching2RoomGroup))); + memcpy(ptr_member->roomGroup.get_ptr(), &room.groups.at(member.group_id), sizeof(SceNpMatching2RoomGroup)); + } + + u32 num_binattrs = 0; + for (u32 i = 0; i < binattrs_list.size(); i++) + { + if (member.bins.contains(binattrs_list[i])) + { + num_binattrs++; + } + } + + if (num_binattrs) + { + ptr_member->roomMemberBinAttrInternal.set(mem.allocate(sizeof(SceNpMatching2RoomMemberBinAttrInternal) * num_binattrs)); + ptr_member->roomMemberBinAttrInternalNum = num_binattrs; + SceNpMatching2RoomMemberBinAttrInternal* bin_ptr = ptr_member->roomMemberBinAttrInternal.get_ptr(); + + u32 actual_cnt = 0; + for (u32 i = 0; i < binattrs_list.size(); i++) + { + if (member.bins.contains(binattrs_list[i])) + { + const auto& bin = member.bins.at(binattrs_list[i]); + bin_ptr[actual_cnt].updateDate.tick = bin.updateDate.tick; + bin_ptr[actual_cnt].data.id = bin.id; + bin_ptr[actual_cnt].data.size = bin.data.size(); + bin_ptr[actual_cnt].data.ptr.set(mem.allocate(bin.data.size())); + memcpy(bin_ptr[actual_cnt].data.ptr.get_ptr(), bin.data.data(), bin.data.size()); + actual_cnt++; + } + } + } + + return needed_data_size; + } +} // namespace np \ No newline at end of file diff --git a/rpcs3/Emu/NP/np_cache.h b/rpcs3/Emu/NP/np_cache.h new file mode 100644 index 0000000000..8ac7ef54f6 --- /dev/null +++ b/rpcs3/Emu/NP/np_cache.h @@ -0,0 +1,83 @@ +#pragma once + +#include +#include + +#include "Utilities/mutex.h" + +#include "Emu/Cell/Modules/sceNp.h" +#include "Emu/Cell/Modules/sceNp2.h" + +namespace np +{ + struct userinfo_cache + { + SceNpId npId; + std::optional onlineName; + std::optional avatarUrl; + }; + + struct memberbin_cache + { + memberbin_cache(SceNpMatching2RoomMemberBinAttrInternal* sce_memberbin); + + SceNpMatching2AttributeId id; + CellRtcTick updateDate; + std::vector data; + }; + + struct member_cache + { + member_cache(const SceNpMatching2RoomMemberDataInternal* sce_member); + + userinfo_cache userInfo; + CellRtcTick joinDate; + SceNpMatching2RoomMemberId memberId; + SceNpMatching2TeamId teamId; + SceNpMatching2RoomGroupId group_id; + SceNpMatching2NatType natType; + SceNpMatching2FlagAttr flagAttr; + + std::map bins; + }; + + struct password_info_cache + { + bool with_password = false; + SceNpMatching2SessionPassword password{}; + }; + + struct room_cache + { + void update(const SceNpMatching2RoomDataInternal* sce_roomdata); + + u32 num_slots = 0; + SceNpMatching2RoomPasswordSlotMask mask_password = 0; + std::optional password; + + std::map groups; + std::map members; + + bool owner = false; + }; + + class cache_manager + { + public: + cache_manager() = default; + + void insert_room(const SceNpMatching2RoomDataInternal* sce_roomdata); + void add_member(SceNpMatching2RoomId room_id, const SceNpMatching2RoomMemberDataInternal* sce_roommemberdata); + void del_member(SceNpMatching2RoomId room_id, SceNpMatching2RoomMemberId member_id); + void update_password(SceNpMatching2RoomId room_id, const std::optional& password); + + std::pair> get_slots(SceNpMatching2RoomId room_id); + std::pair> get_memberids(u64 room_id, s32 sort_method); + std::pair> get_password(SceNpMatching2RoomId room_id); + error_code get_member_and_attrs(SceNpMatching2RoomId room_id, SceNpMatching2RoomMemberId member_id, const std::vector& binattrs_list, SceNpMatching2RoomMemberDataInternal* ptr_member, u32 addr_data, u32 size_data); + + private: + shared_mutex mutex; + std::map rooms; + }; +} // namespace np diff --git a/rpcs3/Emu/NP/np_dnshook.cpp b/rpcs3/Emu/NP/np_dnshook.cpp new file mode 100644 index 0000000000..b8ea108f5f --- /dev/null +++ b/rpcs3/Emu/NP/np_dnshook.cpp @@ -0,0 +1,174 @@ +#include "stdafx.h" +#include "np_dnshook.h" + +#include "Emu/system_config.h" +#include "Utilities/StrUtil.h" +#include "util/logs.hpp" + +#ifdef _WIN32 +#include +#else +#include +#include +#endif + +LOG_CHANNEL(dnshook_log, "DnsHook"); + +namespace np +{ + dnshook::dnshook() + { + // Init switch map for dns + auto swaps = fmt::split(g_cfg.net.swap_list.to_string(), {"&&"}); + for (usz i = 0; i < swaps.size(); i++) + { + auto host_and_ip = fmt::split(swaps[i], {"="}); + if (host_and_ip.size() != 2) + { + dnshook_log.error("Pattern <%s> contains more than one '='", swaps[i]); + continue; + } + + in_addr conv; + if (!inet_pton(AF_INET, host_and_ip[1].c_str(), &conv)) + { + dnshook_log.error("IP(%s) provided for %s in the switch list is invalid!", host_and_ip[1], host_and_ip[0]); + } + else + { + switch_map[host_and_ip[0]] = conv.s_addr; + } + } + } + + void dnshook::add_dns_spy(u32 sock) + { + std::lock_guard lock(mutex); + dns_spylist.emplace(std::make_pair(sock, std::queue>())); + } + + void dnshook::remove_dns_spy(u32 sock) + { + std::lock_guard lock(mutex); + dns_spylist.erase(sock); + } + + bool dnshook::is_dns(u32 sock) + { + std::lock_guard lock(mutex); + return dns_spylist.contains(sock); + } + + bool dnshook::is_dns_queue(u32 sock) + { + std::lock_guard lock(mutex); + return !dns_spylist.at(sock).empty(); + } + + std::vector dnshook::get_dns_packet(u32 sock) + { + std::lock_guard lock(mutex); + auto ret_vec = std::move(dns_spylist.at(sock).front()); + dns_spylist.at(sock).pop(); + + return ret_vec; + } + + s32 dnshook::analyze_dns_packet(s32 s, const u8* buf, u32 len) + { + std::lock_guard lock(mutex); + if (dnshook_log.enabled == logs::level::trace) + { + std::string datrace; + const char hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; + + for (u32 index = 0; index < len; index++) + { + if ((index % 16) == 0) + datrace += '\n'; + + datrace += hex[(buf[index] >> 4) & 15]; + datrace += hex[(buf[index]) & 15]; + datrace += ' '; + } + dnshook_log.trace("DNS REQUEST: %s", datrace); + } + + struct dns_header + { + u16 id; // identification number + + u8 rd : 1; // recursion desired + u8 tc : 1; // truncated message + u8 aa : 1; // authoritive answer + u8 opcode : 4; // purpose of message + u8 qr : 1; // query/response flag + + u8 rcode : 4; // response code + u8 cd : 1; // checking disabled + u8 ad : 1; // authenticated data + u8 z : 1; // its z! reserved + u8 ra : 1; // recursion available + + be_t q_count; // number of question entries + be_t ans_count; // number of answer entries + be_t auth_count; // number of authority entries + be_t add_count; // number of resource entries + }; + + if (len < sizeof(dns_header)) + return -1; + + const dns_header* dhead = reinterpret_cast(buf); + // We are only looking for queries not truncated(todo?), only handle one dns query at a time(todo?) + if (dhead->qr != 0 || dhead->tc != 0 || dhead->q_count != 1 || dhead->ans_count != 0 || dhead->auth_count != 0 || dhead->add_count != 0) + return -1; + + // Get the actual address + u8 count = 0; + std::string host{}; + for (u32 i = sizeof(dns_header); (i < len) && buf[i] != 0; i++) + { + if (count == 0) + { + count = buf[i]; + if (i != sizeof(dns_header)) + { + host += '.'; + } + } + else + { + host += static_cast(buf[i]); + count--; + } + } + + dnshook_log.warning("DNS query for %s", host); + + if (switch_map.contains(host)) + { + // design fake packet + std::vector fake(len); + memcpy(fake.data(), buf, len); + dns_header* fake_header = reinterpret_cast(fake.data()); + fake_header->qr = 1; + fake_header->ra = 1; + fake_header->ans_count = 1; + fake.insert(fake.end(), {0xC0, 0x0C}); // Ref to name in header + fake.insert(fake.end(), {0x00, 0x01}); // IPv4 + fake.insert(fake.end(), {0x00, 0x01}); // Class? + fake.insert(fake.end(), {0x00, 0x00, 0x00, 0x3B}); // TTL + fake.insert(fake.end(), {0x00, 0x04}); // Size of data + u32 ip = switch_map[host]; + u8* ptr_ip = reinterpret_cast(&ip); + fake.insert(fake.end(), ptr_ip, ptr_ip + 4); // IP + + dnshook_log.warning("Solving %s to %d.%d.%d.%d", host, ptr_ip[0], ptr_ip[1], ptr_ip[2], ptr_ip[3]); + + dns_spylist[s].push(std::move(fake)); + return len; + } + return -1; + } +} // namespace np diff --git a/rpcs3/Emu/NP/np_dnshook.h b/rpcs3/Emu/NP/np_dnshook.h new file mode 100644 index 0000000000..de9939c07b --- /dev/null +++ b/rpcs3/Emu/NP/np_dnshook.h @@ -0,0 +1,31 @@ +#pragma once + +#include +#include +#include + +#include "util/types.hpp" +#include "Utilities/mutex.h" + +namespace np +{ + class dnshook + { + public: + dnshook(); + + void add_dns_spy(u32 sock); + void remove_dns_spy(u32 sock); + + bool is_dns(u32 sock); + bool is_dns_queue(u32 sock); + + std::vector get_dns_packet(u32 sock); + s32 analyze_dns_packet(s32 s, const u8* buf, u32 len); + + private: + shared_mutex mutex; + std::map>> dns_spylist{}; + std::map switch_map{}; + }; +} // namespace np diff --git a/rpcs3/Emu/NP/np_handler.cpp b/rpcs3/Emu/NP/np_handler.cpp index 15129c127a..0d1dfd0151 100644 --- a/rpcs3/Emu/NP/np_handler.cpp +++ b/rpcs3/Emu/NP/np_handler.cpp @@ -75,28 +75,6 @@ namespace np { dns_ip = conv.s_addr; } - - // Init switch map for dns - auto swaps = fmt::split(g_cfg.net.swap_list.to_string(), {"&&"}); - for (usz i = 0; i < swaps.size(); i++) - { - auto host_and_ip = fmt::split(swaps[i], {"="}); - if (host_and_ip.size() != 2) - { - nph_log.error("Pattern <%s> contains more than one '='", swaps[i]); - continue; - } - - in_addr conv; - if (!inet_pton(AF_INET, host_and_ip[1].c_str(), &conv)) - { - nph_log.error("IP(%s) provided for %s in the switch list is invalid!", host_and_ip[1], host_and_ip[0]); - } - else - { - switch_map[host_and_ip[0]] = conv.s_addr; - } - } } } @@ -551,132 +529,6 @@ namespace np } } - void np_handler::add_dns_spy(u32 sock) - { - dns_spylist.emplace(std::make_pair(sock, std::queue>())); - } - - void np_handler::remove_dns_spy(u32 sock) - { - dns_spylist.erase(sock); - } - - bool np_handler::is_dns(u32 sock) const - { - return dns_spylist.contains(sock); - } - - bool np_handler::is_dns_queue(u32 sock) const - { - return !dns_spylist.at(sock).empty(); - } - - std::vector np_handler::get_dns_packet(u32 sock) - { - auto ret_vec = std::move(dns_spylist.at(sock).front()); - dns_spylist.at(sock).pop(); - - return ret_vec; - } - - s32 np_handler::analyze_dns_packet(s32 s, const u8* buf, u32 len) - { - if (sys_net.enabled == logs::level::trace) - { - std::string datrace; - const char hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; - - for (u32 index = 0; index < len; index++) - { - if ((index % 16) == 0) - datrace += '\n'; - - datrace += hex[(buf[index] >> 4) & 15]; - datrace += hex[(buf[index]) & 15]; - datrace += ' '; - } - sys_net.trace("DNS REQUEST: %s", datrace); - } - - struct dns_header - { - u16 id; // identification number - - u8 rd : 1; // recursion desired - u8 tc : 1; // truncated message - u8 aa : 1; // authoritive answer - u8 opcode : 4; // purpose of message - u8 qr : 1; // query/response flag - - u8 rcode : 4; // response code - u8 cd : 1; // checking disabled - u8 ad : 1; // authenticated data - u8 z : 1; // its z! reserved - u8 ra : 1; // recursion available - - be_t q_count; // number of question entries - be_t ans_count; // number of answer entries - be_t auth_count; // number of authority entries - be_t add_count; // number of resource entries - }; - - if (len < sizeof(dns_header)) - return -1; - - const dns_header* dhead = reinterpret_cast(buf); - // We are only looking for queries not truncated(todo?), only handle one dns query at a time(todo?) - if (dhead->qr != 0 || dhead->tc != 0 || dhead->q_count != 1 || dhead->ans_count != 0 || dhead->auth_count != 0 || dhead->add_count != 0) - return -1; - - // Get the actual address - u8 count = 0; - std::string host{}; - for (u32 i = sizeof(dns_header); (i < len) && buf[i] != 0; i++) - { - if (count == 0) - { - count = buf[i]; - if (i != sizeof(dns_header)) - { - host += '.'; - } - } - else - { - host += static_cast(buf[i]); - count--; - } - } - - sys_net.warning("DNS query for %s", host); - - if (switch_map.contains(host)) - { - // design fake packet - std::vector fake(len); - memcpy(fake.data(), buf, len); - dns_header* fake_header = reinterpret_cast(fake.data()); - fake_header->qr = 1; - fake_header->ra = 1; - fake_header->ans_count = 1; - fake.insert(fake.end(), {0xC0, 0x0C}); // Ref to name in header - fake.insert(fake.end(), {0x00, 0x01}); // IPv4 - fake.insert(fake.end(), {0x00, 0x01}); // Class? - fake.insert(fake.end(), {0x00, 0x00, 0x00, 0x3B}); // TTL - fake.insert(fake.end(), {0x00, 0x04}); // Size of data - u32 ip = switch_map[host]; - u8* ptr_ip = reinterpret_cast(&ip); - fake.insert(fake.end(), ptr_ip, ptr_ip + 4); // IP - - sys_net.warning("Solving %s to %d.%d.%d.%d", host, ptr_ip[0], ptr_ip[1], ptr_ip[2], ptr_ip[3]); - - dns_spylist[s].push(std::move(fake)); - return len; - } - - return -1; - } - bool np_handler::error_and_disconnect(const std::string& error_msg) { rpcn_log.error("%s", error_msg); @@ -751,4 +603,23 @@ namespace np return rpcn->get_num_blocks(); } + std::pair> np_handler::local_get_room_password(SceNpMatching2RoomId room_id) + { + return np_cache.get_password(room_id); + } + + std::pair> np_handler::local_get_room_slots(SceNpMatching2RoomId room_id) + { + return np_cache.get_slots(room_id); + } + + std::pair> np_handler::local_get_room_memberids(SceNpMatching2RoomId room_id, s32 sort_method) + { + return np_cache.get_memberids(room_id, sort_method); + } + + error_code np_handler::local_get_room_member_data(SceNpMatching2RoomId room_id, SceNpMatching2RoomMemberId member_id, const std::vector& binattrs_list, SceNpMatching2RoomMemberDataInternal* ptr_member, u32 addr_data, u32 size_data) + { + return np_cache.get_member_and_attrs(room_id, member_id, binattrs_list, ptr_member, addr_data, size_data); + } } // namespace np diff --git a/rpcs3/Emu/NP/np_handler.h b/rpcs3/Emu/NP/np_handler.h index b9fdc2f1b7..f4d1d7f001 100644 --- a/rpcs3/Emu/NP/np_handler.h +++ b/rpcs3/Emu/NP/np_handler.h @@ -11,8 +11,9 @@ #include "Emu/NP/rpcn_client.h" #include "generated/np2_structs_generated.h" #include "signaling_handler.h" -#include "np_event_data.h" #include "np_allocator.h" +#include "np_cache.h" +#include "np_event_data.h" namespace np { @@ -51,14 +52,6 @@ namespace np const SceNpOnlineName& get_online_name() const; const SceNpAvatarUrl& get_avatar_url() const; - // DNS hooking functions - void add_dns_spy(u32 sock); - void remove_dns_spy(u32 sock); - bool is_dns(u32 sock) const; - bool is_dns_queue(u32 sock) const; - std::vector get_dns_packet(u32 sock); - s32 analyze_dns_packet(s32 s, const u8* buf, u32 len); - // handles async messages from server(only needed for RPCN) void operator()(); @@ -91,6 +84,8 @@ namespace np void queue_basic_event(basic_event to_queue); bool send_basic_event(s32 event, s32 retCode, u32 reqId); error_code get_basic_event(vm::ptr event, vm::ptr from, vm::ptr data, vm::ptr size); + + // Messages-related functions std::optional>> get_message(u64 id); // Those should probably be under match2 ctx @@ -121,6 +116,12 @@ namespace np u32 get_match2_event(SceNpMatching2EventKey event_key, u32 dest_addr, u32 size); + // Local functions + std::pair> local_get_room_slots(SceNpMatching2RoomId room_id); + std::pair> local_get_room_password(SceNpMatching2RoomId room_id); + std::pair> local_get_room_memberids(SceNpMatching2RoomId room_id, s32 sort_method); + error_code local_get_room_member_data(SceNpMatching2RoomId room_id, SceNpMatching2RoomMemberId member_id, const std::vector& binattrs_list, SceNpMatching2RoomMemberDataInternal* ptr_member, u32 addr_data, u32 size_data); + // Friend stuff u32 get_num_friends(); u32 get_num_blocks(); @@ -227,13 +228,13 @@ namespace np SceNpOnlineName online_name{}; SceNpAvatarUrl avatar_url{}; - // DNS related - std::map>> dns_spylist{}; - std::map switch_map{}; - // Memory pool for sceNp/sceNp2 memory_allocator np_memory; + // Cache related + std::optional cached_cj_password; + cache_manager np_cache; + // Requests(reqEventKey : data) shared_mutex mutex_match2_req_results; std::unordered_map match2_req_results; diff --git a/rpcs3/Emu/NP/np_notifications.cpp b/rpcs3/Emu/NP/np_notifications.cpp index f8c569df54..9a4bf0305c 100644 --- a/rpcs3/Emu/NP/np_notifications.cpp +++ b/rpcs3/Emu/NP/np_notifications.cpp @@ -29,6 +29,8 @@ namespace np RoomMemberUpdateInfo_to_SceNpMatching2RoomMemberUpdateInfo(edata, update_info, notif_data); np_memory.shrink_allocation(edata.addr(), edata.size()); + np_cache.add_member(room_id, notif_data->roomMemberDataInternal.get_ptr()); + rpcn_log.notice("Received notification that user %s(%d) joined the room(%d)", notif_data->roomMemberDataInternal->userInfo.npId.handle.data, notif_data->roomMemberDataInternal->memberId, room_id); extra_nps::print_room_member_data_internal(notif_data->roomMemberDataInternal.get_ptr()); @@ -59,6 +61,8 @@ namespace np RoomMemberUpdateInfo_to_SceNpMatching2RoomMemberUpdateInfo(edata, update_info, notif_data); np_memory.shrink_allocation(edata.addr(), edata.size()); + np_cache.del_member(room_id, notif_data->roomMemberDataInternal->memberId); + rpcn_log.notice("Received notification that user %s(%d) left the room(%d)", notif_data->roomMemberDataInternal->userInfo.npId.handle.data, notif_data->roomMemberDataInternal->memberId, room_id); extra_nps::print_room_member_data_internal(notif_data->roomMemberDataInternal.get_ptr()); @@ -121,13 +125,12 @@ namespace np RoomDataInternalUpdateInfo_to_SceNpMatching2RoomDataInternalUpdateInfo(edata, update_info, notif_data, npid); np_memory.shrink_allocation(edata.addr(), edata.size()); + np_cache.insert_room(notif_data->newRoomDataInternal.get_ptr()); + extra_nps::print_room_data_internal(notif_data->newRoomDataInternal.get_ptr()); rpcn_log.notice("Received notification that room(%d)'s data was updated", room_id); - auto& sigh = g_fxo->get>(); - sigh.disconnect_sig2_users(room_id); - sysutil_register_cb([room_event_cb = this->room_event_cb, room_event_cb_ctx = this->room_event_cb_ctx, room_id, event_key, room_event_cb_arg = this->room_event_cb_arg, size = edata.size()](ppu_thread& cb_ppu) -> s32 { room_event_cb(cb_ppu, room_event_cb_ctx, room_id, SCE_NP_MATCHING2_ROOM_EVENT_UpdatedRoomDataInternal, event_key, 0, size, room_event_cb_arg); @@ -155,6 +158,8 @@ namespace np RoomMemberDataInternalUpdateInfo_to_SceNpMatching2RoomMemberDataInternalUpdateInfo(edata, update_info, notif_data); np_memory.shrink_allocation(edata.addr(), edata.size()); + np_cache.add_member(room_id, notif_data->newRoomMemberDataInternal.get_ptr()); + rpcn_log.notice("Received notification that user's %s(%d) room (%d) data was updated", notif_data->newRoomMemberDataInternal->userInfo.npId.handle.data, notif_data->newRoomMemberDataInternal->memberId, room_id); extra_nps::print_room_member_data_internal(notif_data->newRoomMemberDataInternal.get_ptr()); diff --git a/rpcs3/Emu/NP/np_requests.cpp b/rpcs3/Emu/NP/np_requests.cpp index d066cb6c5c..ef8e22b374 100644 --- a/rpcs3/Emu/NP/np_requests.cpp +++ b/rpcs3/Emu/NP/np_requests.cpp @@ -97,7 +97,6 @@ namespace np if (reply.is_error()) { - world_list.clear(); return error_and_disconnect("Malformed reply to GetWorldList command"); } @@ -142,6 +141,9 @@ namespace np is_psn_active = false; } + // More elegant solution would be to send back password with creation reply + cached_cj_password = req->roomPassword ? std::optional{*req->roomPassword} : std::nullopt; + return req_id; } @@ -164,6 +166,9 @@ namespace np RoomDataInternal_to_SceNpMatching2RoomDataInternal(edata, resp, room_info, npid); np_memory.shrink_allocation(edata.addr(), edata.size()); + np_cache.insert_room(room_info); + np_cache.update_password(room_resp->roomDataInternal->roomId, cached_cj_password); + // Establish Matching2 self signaling info auto& sigh = g_fxo->get>(); sigh.set_self_sig2_info(room_info->roomId, 1); @@ -214,7 +219,9 @@ namespace np u16 member_id = RoomDataInternal_to_SceNpMatching2RoomDataInternal(edata, resp, room_info, npid); np_memory.shrink_allocation(edata.addr(), edata.size()); - extra_nps::print_room_data_internal(room_resp->roomDataInternal.get_ptr()); + np_cache.insert_room(room_info); + + extra_nps::print_room_data_internal(room_info); // Establish Matching2 self signaling info auto& sigh = g_fxo->get>(); @@ -409,7 +416,9 @@ namespace np RoomDataInternal_to_SceNpMatching2RoomDataInternal(edata, resp, room_info, npid); np_memory.shrink_allocation(edata.addr(), edata.size()); - extra_nps::print_room_data_internal(room_resp->roomDataInternal.get_ptr()); + np_cache.insert_room(room_info); + + extra_nps::print_room_data_internal(room_info); sysutil_register_cb([=, size = edata.size()](ppu_thread& cb_ppu) -> s32 { diff --git a/rpcs3/Emu/NP/rpcn_client.cpp b/rpcs3/Emu/NP/rpcn_client.cpp index e52ea4a884..6ea5152333 100644 --- a/rpcs3/Emu/NP/rpcn_client.cpp +++ b/rpcs3/Emu/NP/rpcn_client.cpp @@ -1667,7 +1667,7 @@ namespace rpcn case CreationBannedEmailProvider: rpcn_log.error("Error creating an account: banned email provider!"); break; case CreationExistingEmail: rpcn_log.error("Error creating an account: an account with that email already exist!"); break; case AlreadyJoined: rpcn_log.error("User has already joined!"); break; - case Unauthorized: rpcn_log.error("User attempted an unauthorized operation!"); + case Unauthorized: rpcn_log.error("User attempted an unauthorized operation!"); break; case DbFail: rpcn_log.error("A db query failed on the server!"); break; case EmailFail: rpcn_log.error("An email action failed on the server!"); break; case NotFound: rpcn_log.error("A request replied not found!"); break; diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index a577170d18..e3fa6f4de6 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -91,7 +91,9 @@ + + @@ -466,6 +468,8 @@ + + diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index ae45394d3e..551fa21f30 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -891,9 +891,15 @@ Emu\NP + + Emu\NP + Emu\NP + + Emu\NP + Emu\NP