NP code review

sceNpTrophy fixes

- sceNpTrophyGetTrophyUnlockState: signed 1 was potentially shifted by 31(UB)
- sceNpTrophyUnlockTrophy: used a reader_lock and was missing check for read only context

cellGame fixes

- cellHddGameCheck: missing log parameters
- cellGameDataCheckCreate2: missing log parameter
- cellGameThemeInstall: condition inverted checking for extension + added tolower just in case
- cellGameThemeInstallFromBuffer: OOB access, buf is always filled from the start and then used as a parameter to the CB

sceNp fixes

- sceNpManagerGetTicket: Made accurate from RE
- sceNpDrmGetTimelimit: Fix msec calculation

sceNp2 fixes

-sceNpMatching2ContextStartAsync: avoid capturing ctx
-sceNpMatching2ContextStop: Minor error value swap

rpcn_client fixes

-add_friend: missing log parameter
-handle_friend_notification: misc validation issue

np_handler fixes
-ticket: Missing move in move constructor
-ticket::parse: Misc validation fix
-get_player_history_entry: potential UB fix

np_requests fixes

-Wrong CB event_type set for get_room_member_data_external_list!
-reply_tus_get_data was not copying status data!
-Order of error check in reply_get_room_member_data_external_list was wrong
-Improved logging

np_requests_gui:

-Added missing guards for gui_notifications

upnp_handler fixes

-Highest density of bugs per line of code in the west, let's pretend I never wrote this

signaling_handler fixes

-Swapped to multimap to avoid collisions on timestamps

Misc fixes
This commit is contained in:
RipleyTom
2026-02-28 18:55:31 +01:00
committed by Elad
parent 198c2e9eb8
commit 5ca19eabd5
16 changed files with 111 additions and 89 deletions
+1 -1
View File
@@ -329,7 +329,7 @@ bool patch_engine::load(patch_map& patches_map, const std::string& path, std::st
is_valid = false; is_valid = false;
continue; continue;
} }
else if (serial.size() != 9 || !std::all_of(serial.begin(), serial.end(), [](char c) { return std::isalnum(c); })) else if (serial.size() != 9 || !std::all_of(serial.begin(), serial.end(), [](char c) { return std::isalnum(static_cast<unsigned char>(c)); }))
{ {
append_log_message(log_messages, fmt::format("Error: Serial '%s' invalid (patch: %s, key: %s, location: %s, file: %s)", serial, description, main_key, get_yaml_node_location(serial_node), path), &patch_log.error); append_log_message(log_messages, fmt::format("Error: Serial '%s' invalid (patch: %s, key: %s, location: %s, file: %s)", serial, description, main_key, get_yaml_node_location(serial_node), path), &patch_log.error);
is_valid = false; is_valid = false;
+6 -6
View File
@@ -492,8 +492,8 @@ error_code cellHddGameCheck(ppu_thread& ppu, u32 version, vm::cptr<char> dirName
strcpy_trunc(get->getParam.titleLang[i], psf::get_string(psf, fmt::format("TITLE_%02d", i))); strcpy_trunc(get->getParam.titleLang[i], psf::get_string(psf, fmt::format("TITLE_%02d", i)));
} }
cellGame.warning("cellHddGameCheck(): Data exists:\nATTRIBUTE: 0x%x, RESOLUTION: 0x%x, RESOLUTION: 0x%x, SOUND_FORMAT: 0x%x, dataVersion: %s" cellGame.warning("cellHddGameCheck(): Data exists:\nATTRIBUTE: 0x%x, RESOLUTION: 0x%x, SOUND_FORMAT: 0x%x, dataVersion: %s"
, get->getParam.attribute, get->getParam.resolution, get->getParam.soundFormat, get->getParam.soundFormat, std::span<const u8>(reinterpret_cast<const u8*>(get->getParam.dataVersion), 6)); , get->getParam.attribute, get->getParam.resolution, get->getParam.soundFormat, std::span<const u8>(reinterpret_cast<const u8*>(get->getParam.dataVersion), 6));
} }
// TODO ? // TODO ?
@@ -580,7 +580,7 @@ error_code cellHddGameCheck(ppu_thread& ppu, u32 version, vm::cptr<char> dirName
break; break;
default: default:
cellGame.error("cellHddGameCheck(): callback returned unknown error (code=0x%x). Error message: %s", result->invalidMsg); cellGame.error("cellHddGameCheck(): callback returned unknown error (code=0x%x). Error message: %s", result->result, result->invalidMsg);
error_msg = get_localized_string(localized_string_id::CELL_HDD_GAME_CHECK_INVALID, "%s", result->invalidMsg); error_msg = get_localized_string(localized_string_id::CELL_HDD_GAME_CHECK_INVALID, "%s", result->invalidMsg);
break; break;
} }
@@ -1199,7 +1199,7 @@ error_code cellGameDataCheckCreate2(ppu_thread& ppu, u32 version, vm::cptr<char>
break; break;
default: default:
cellGame.error("cellGameDataCheckCreate2(): callback returned unknown error (code=0x%x). Error message: %s", cbResult->invalidMsg); cellGame.error("cellGameDataCheckCreate2(): callback returned unknown error (code=0x%x). Error message: %s", cbResult->result, cbResult->invalidMsg);
error_msg = get_localized_string(localized_string_id::CELL_GAMEDATA_CHECK_INVALID, "%s", cbResult->invalidMsg); error_msg = get_localized_string(localized_string_id::CELL_GAMEDATA_CHECK_INVALID, "%s", cbResult->invalidMsg);
break; break;
} }
@@ -1747,7 +1747,7 @@ error_code cellGameThemeInstall(vm::cptr<char> usrdirPath, vm::cptr<char> fileNa
{ {
u32 magic{}; u32 magic{};
if (src_path.ends_with(".p3t") || !theme.read(magic) || magic != "P3TF"_u32) if (!fmt::to_lower(src_path).ends_with(".p3t") || !theme.read(magic) || magic != "P3TF"_u32)
{ {
return CELL_GAME_ERROR_INVALID_THEME_FILE; return CELL_GAME_ERROR_INVALID_THEME_FILE;
} }
@@ -1819,7 +1819,7 @@ error_code cellGameThemeInstallFromBuffer(ppu_thread& ppu, u32 fileSize, u32 buf
const u32 read_size = std::min(bufSize, fileSize - file_offset); const u32 read_size = std::min(bufSize, fileSize - file_offset);
cellGame.notice("cellGameThemeInstallFromBuffer: writing %d bytes at pos %d", read_size, file_offset); cellGame.notice("cellGameThemeInstallFromBuffer: writing %d bytes at pos %d", read_size, file_offset);
if (theme.write(reinterpret_cast<u8*>(buf.get_ptr()) + file_offset, read_size) != read_size) if (theme.write(reinterpret_cast<u8*>(buf.get_ptr()), read_size) != read_size)
{ {
cellGame.error("cellGameThemeInstallFromBuffer: failed to write to destination file '%s' (error=%s)", dst_path, fs::g_tls_error); cellGame.error("cellGameThemeInstallFromBuffer: failed to write to destination file '%s' (error=%s)", dst_path, fs::g_tls_error);
+6 -9
View File
@@ -871,7 +871,7 @@ error_code sceNpDrmGetTimelimit(vm::cptr<char> path, vm::ptr<u64> time_remain)
} }
// Convert time to milliseconds // Convert time to milliseconds
s64 msec = *sec * 1000ll + *nsec / 1000ll; s64 msec = *sec * 1000ll + *nsec / 1'000'000ll;
// Return the remaining time in microseconds // Return the remaining time in microseconds
if (npd.activate_time != 0 && msec < npd.activate_time) if (npd.activate_time != 0 && msec < npd.activate_time)
@@ -4242,19 +4242,16 @@ error_code sceNpManagerGetTicket(vm::ptr<void> buffer, vm::ptr<u32> bufferSize)
} }
const auto& ticket = nph.get_ticket(); const auto& ticket = nph.get_ticket();
*bufferSize = static_cast<u32>(ticket.size());
if (!buffer) if (!buffer)
{ {
*bufferSize = static_cast<u32>(ticket.size());
return CELL_OK; return CELL_OK;
} }
if (*bufferSize < ticket.size()) const u32 size_read = std::min(::size32(ticket), static_cast<u32>(*bufferSize));
{ std::memcpy(buffer.get_ptr(), ticket.data(), size_read);
return SCE_NP_ERROR_INVALID_ARGUMENT; *bufferSize = size_read;
}
memcpy(buffer.get_ptr(), ticket.data(), ticket.size());
return CELL_OK; return CELL_OK;
} }
@@ -5676,7 +5673,7 @@ error_code scenp_score_record_score(s32 transId, SceNpScoreBoardId boardId, SceN
else else
{ {
data = &gameInfo->nativeData[0]; data = &gameInfo->nativeData[0];
data_size = 64; data_size = sizeof(gameInfo->nativeData);
} }
nph.record_score(trans_ctx, boardId, score, scoreComment, data, data_size, tmpRank, async); nph.record_score(trans_ctx, boardId, score, scoreComment, data, data_size, tmpRank, async);
+2 -2
View File
@@ -1135,7 +1135,7 @@ error_code sceNpMatching2ContextStartAsync(SceNpMatching2ContextId ctxId, u32 ti
{ {
sysutil_register_cb([=, context_callback = ctx->context_callback, context_callback_param = ctx->context_callback_param](ppu_thread& cb_ppu) -> s32 sysutil_register_cb([=, context_callback = ctx->context_callback, context_callback_param = ctx->context_callback_param](ppu_thread& cb_ppu) -> s32
{ {
context_callback(cb_ppu, ctxId, SCE_NP_MATCHING2_CONTEXT_EVENT_Start, SCE_NP_MATCHING2_EVENT_CAUSE_CONTEXT_ACTION, 0, ctx->context_callback_param); context_callback(cb_ppu, ctxId, SCE_NP_MATCHING2_CONTEXT_EVENT_Start, SCE_NP_MATCHING2_EVENT_CAUSE_CONTEXT_ACTION, 0, context_callback_param);
return 0; return 0;
}); });
} }
@@ -1760,7 +1760,7 @@ error_code sceNpMatching2ContextStop(SceNpMatching2ContextId ctxId)
const auto ctx = get_match2_context(ctxId); const auto ctx = get_match2_context(ctxId);
if (!ctx) if (!ctx)
return SCE_NP_MATCHING2_ERROR_INVALID_CONTEXT_ID; return SCE_NP_MATCHING2_ERROR_CONTEXT_NOT_FOUND;
if (!ctx->started.compare_and_swap_test(1, 0)) if (!ctx->started.compare_and_swap_test(1, 0))
return SCE_NP_MATCHING2_ERROR_CONTEXT_NOT_STARTED; return SCE_NP_MATCHING2_ERROR_CONTEXT_NOT_STARTED;
+4 -4
View File
@@ -1026,14 +1026,14 @@ error_code sceNpTrophyUnlockTrophy(ppu_thread& ppu, u32 context, u32 handle, s32
auto& trophy_manager = g_fxo->get<sce_np_trophy_manager>(); auto& trophy_manager = g_fxo->get<sce_np_trophy_manager>();
reader_lock lock(trophy_manager.mtx); std::scoped_lock lock(trophy_manager.mtx);
if (!trophy_manager.is_initialized) if (!trophy_manager.is_initialized)
{ {
return SCE_NP_TROPHY_ERROR_NOT_INITIALIZED; return SCE_NP_TROPHY_ERROR_NOT_INITIALIZED;
} }
const auto [ctxt, error] = trophy_manager.get_context_ex(context, handle); const auto [ctxt, error] = trophy_manager.get_context_ex(context, handle, true);
if (error) if (error)
{ {
@@ -1184,9 +1184,9 @@ error_code sceNpTrophyGetTrophyUnlockState(u32 context, u32 handle, vm::ptr<SceN
for (u32 id = 0; id < count_; id++) for (u32 id = 0; id < count_; id++)
{ {
if (tropusr->GetTrophyUnlockState(id)) if (tropusr->GetTrophyUnlockState(id))
flags->flag_bits[id / 32] |= 1 << (id % 32); flags->flag_bits[id / 32] |= 1u << (id % 32);
else else
flags->flag_bits[id / 32] &= ~(1 << (id % 32)); flags->flag_bits[id / 32] &= ~(1u << (id % 32));
} }
return CELL_OK; return CELL_OK;
+7 -8
View File
@@ -111,7 +111,7 @@ namespace np
} }
ticket::ticket(std::vector<u8>&& raw_data) ticket::ticket(std::vector<u8>&& raw_data)
: raw_data(raw_data) : raw_data(std::move(raw_data))
{ {
parse(); parse();
} }
@@ -387,7 +387,7 @@ namespace np
return; return;
} }
if (nodes[0].id != 0x3000 && nodes[1].id != 0x3002) if (nodes[0].id != 0x3000 || nodes[1].id != 0x3002)
{ {
ticket_log.error("The 2 blobs ids are incorrect"); ticket_log.error("The 2 blobs ids are incorrect");
return; return;
@@ -1467,14 +1467,13 @@ namespace np
if (all_history) if (all_history)
{ {
if (index >= players_history.size())
return false;
auto it = players_history.begin(); auto it = players_history.begin();
std::advance(it, index); std::advance(it, index);
string_to_npid(it->first, *npid);
if (it != players_history.end()) return true;
{
string_to_npid(it->first, *npid);
return true;
}
} }
else else
{ {
+2 -2
View File
@@ -20,7 +20,7 @@ namespace np
return std::string(ip_str); return std::string(ip_str);
} }
std::string ether_to_string(std::array<u8, 6>& ether) std::string ether_to_string(const std::array<u8, 6>& ether)
{ {
return fmt::format("%02X:%02X:%02X:%02X:%02X:%02X", ether[0], ether[1], ether[2], ether[3], ether[4], ether[5]); return fmt::format("%02X:%02X:%02X:%02X:%02X:%02X", ether[0], ether[1], ether[2], ether[3], ether[4], ether[5]);
} }
@@ -110,7 +110,7 @@ namespace np
bool is_valid_npid(const SceNpId& npid) bool is_valid_npid(const SceNpId& npid)
{ {
if (!std::all_of(npid.handle.data, npid.handle.data + 16, [](char c) { return std::isalnum(c) || c == '-' || c == '_' || c == 0; } ) if (!std::all_of(npid.handle.data, npid.handle.data + 16, [](char c) { return std::isalnum(static_cast<unsigned char>(c)) || c == '-' || c == '_' || c == 0; } )
|| npid.handle.data[16] != 0 || npid.handle.data[16] != 0
|| !std::all_of(npid.handle.dummy, npid.handle.dummy + 3, [](char val) { return val == 0; }) ) || !std::all_of(npid.handle.dummy, npid.handle.dummy + 3, [](char val) { return val == 0; }) )
{ {
+1 -1
View File
@@ -7,7 +7,7 @@
namespace np namespace np
{ {
std::string ip_to_string(u32 addr); std::string ip_to_string(u32 addr);
std::string ether_to_string(std::array<u8, 6>& ether); std::string ether_to_string(const std::array<u8, 6>& ether);
bool validate_communication_id(const SceNpCommunicationId& com_id); bool validate_communication_id(const SceNpCommunicationId& com_id);
std::string communication_id_to_string(const SceNpCommunicationId& communicationId); std::string communication_id_to_string(const SceNpCommunicationId& communicationId);
std::optional<SceNpCommunicationId> string_to_communication_id(std::string_view str); std::optional<SceNpCommunicationId> string_to_communication_id(std::string_view str);
+3
View File
@@ -381,7 +381,10 @@ namespace np
auto ctx = get_matching_context(ctx_id); auto ctx = get_matching_context(ctx_id);
if (!ctx) if (!ctx)
{
np_memory.free(edata.addr());
return; return;
}
gui_cache.add_room(room_info->room_status.id); gui_cache.add_room(room_info->room_status.id);
+34 -30
View File
@@ -191,7 +191,7 @@ namespace np
case rpcn::ErrorType::RoomGroupMaxSlotMismatch: error_code = SCE_NP_MATCHING2_SERVER_ERROR_MAX_OVER_SLOT_GROUP; break; case rpcn::ErrorType::RoomGroupMaxSlotMismatch: error_code = SCE_NP_MATCHING2_SERVER_ERROR_MAX_OVER_SLOT_GROUP; break;
case rpcn::ErrorType::RoomPasswordMissing: error_code = SCE_NP_MATCHING2_SERVER_ERROR_NO_PASSWORD; break; case rpcn::ErrorType::RoomPasswordMissing: error_code = SCE_NP_MATCHING2_SERVER_ERROR_NO_PASSWORD; break;
case rpcn::ErrorType::RoomGroupNoJoinLabel: error_code = SCE_NP_MATCHING2_SERVER_ERROR_NO_JOIN_GROUP_LABEL; break; case rpcn::ErrorType::RoomGroupNoJoinLabel: error_code = SCE_NP_MATCHING2_SERVER_ERROR_NO_JOIN_GROUP_LABEL; break;
default: fmt::throw_exception("Unexpected error in reply to CreateRoom: %d", static_cast<u8>(error)); default: fmt::throw_exception("Unexpected error in reply to CreateRoom: %s", error);
} }
if (error_code != CELL_OK) if (error_code != CELL_OK)
@@ -262,7 +262,7 @@ namespace np
case rpcn::ErrorType::RoomPasswordMismatch: error_code = SCE_NP_MATCHING2_SERVER_ERROR_PASSWORD_MISMATCH; break; case rpcn::ErrorType::RoomPasswordMismatch: error_code = SCE_NP_MATCHING2_SERVER_ERROR_PASSWORD_MISMATCH; break;
case rpcn::ErrorType::RoomGroupFull: error_code = SCE_NP_MATCHING2_SERVER_ERROR_GROUP_FULL; break; case rpcn::ErrorType::RoomGroupFull: error_code = SCE_NP_MATCHING2_SERVER_ERROR_GROUP_FULL; break;
case rpcn::ErrorType::RoomGroupJoinLabelNotFound: error_code = SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_GROUP; break; case rpcn::ErrorType::RoomGroupJoinLabelNotFound: error_code = SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_GROUP; break;
default: fmt::throw_exception("Unexpected error in reply to JoinRoom: %d", static_cast<u8>(error)); default: fmt::throw_exception("Unexpected error in reply to JoinRoom: %s", error);
} }
if (error_code != 0) if (error_code != 0)
@@ -348,7 +348,7 @@ namespace np
case rpcn::ErrorType::NoError: break; case rpcn::ErrorType::NoError: break;
case rpcn::ErrorType::NotFound: error_code = SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_ROOM; break; // Unsure if this should return another error(missing user in room has no appropriate error code) case rpcn::ErrorType::NotFound: error_code = SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_ROOM; break; // Unsure if this should return another error(missing user in room has no appropriate error code)
case rpcn::ErrorType::RoomMissing: error_code = SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_ROOM; break; case rpcn::ErrorType::RoomMissing: error_code = SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_ROOM; break;
default: fmt::throw_exception("Unexpected error in reply to LeaveRoom: %d", static_cast<u8>(error)); default: fmt::throw_exception("Unexpected error in reply to LeaveRoom: %s", error);
} }
if (error_code != CELL_OK) if (error_code != CELL_OK)
@@ -447,7 +447,7 @@ namespace np
u32 np_handler::get_room_member_data_external_list(SceNpMatching2ContextId ctx_id, vm::cptr<SceNpMatching2RequestOptParam> optParam, const SceNpMatching2GetRoomMemberDataExternalListRequest* req) u32 np_handler::get_room_member_data_external_list(SceNpMatching2ContextId ctx_id, vm::cptr<SceNpMatching2RequestOptParam> optParam, const SceNpMatching2GetRoomMemberDataExternalListRequest* req)
{ {
const u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_GetRoomDataExternalList, true); const u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_GetRoomMemberDataExternalList, true);
if (!get_rpcn()->get_room_member_data_external_list(req_id, get_match2_context(ctx_id)->communicationId, req->roomId)) if (!get_rpcn()->get_room_member_data_external_list(req_id, get_match2_context(ctx_id)->communicationId, req->roomId))
{ {
@@ -465,13 +465,18 @@ namespace np
if (!cb_info_opt) if (!cb_info_opt)
return; return;
ensure(error == rpcn::ErrorType::NoError, "Unexpected error in GetRoomMemberDataExternalList reply"); switch (error)
{
if (error == rpcn::ErrorType::RoomMissing) case rpcn::ErrorType::NoError:
break;
case rpcn::ErrorType::RoomMissing:
{ {
cb_info_opt->queue_callback(req_id, 0, SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_ROOM, 0); cb_info_opt->queue_callback(req_id, 0, SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_ROOM, 0);
return; return;
} }
default:
fmt::throw_exception("Unexpected error in GetRoomMemberDataExternalList reply: %s", error);
}
const auto resp = reply.get_protobuf<np2_structs::GetRoomMemberDataExternalListResponse>(); const auto resp = reply.get_protobuf<np2_structs::GetRoomMemberDataExternalListResponse>();
ensure(!reply.is_error(), "Malformed reply to GetRoomMemberDataExternalList command"); ensure(!reply.is_error(), "Malformed reply to GetRoomMemberDataExternalList command");
@@ -518,7 +523,7 @@ namespace np
case rpcn::ErrorType::NoError: break; case rpcn::ErrorType::NoError: break;
case rpcn::ErrorType::RoomMissing: error_code = SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_ROOM; break; case rpcn::ErrorType::RoomMissing: error_code = SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_ROOM; break;
case rpcn::ErrorType::Unauthorized: error_code = SCE_NP_MATCHING2_SERVER_ERROR_FORBIDDEN; break; case rpcn::ErrorType::Unauthorized: error_code = SCE_NP_MATCHING2_SERVER_ERROR_FORBIDDEN; break;
default: fmt::throw_exception("Unexpected error in reply to SetRoomDataExternal: %d", static_cast<u8>(error)); default: fmt::throw_exception("Unexpected error in reply to SetRoomDataExternal: %s", error);
} }
cb_info_opt->queue_callback(req_id, 0, error_code, 0); cb_info_opt->queue_callback(req_id, 0, error_code, 0);
@@ -550,7 +555,7 @@ namespace np
{ {
case rpcn::ErrorType::NoError: break; case rpcn::ErrorType::NoError: break;
case rpcn::ErrorType::RoomMissing: error_code = SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_ROOM; break; case rpcn::ErrorType::RoomMissing: error_code = SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_ROOM; break;
default: fmt::throw_exception("Unexpected error in reply to GetRoomDataInternal: %d", static_cast<u8>(error)); default: fmt::throw_exception("Unexpected error in reply to GetRoomDataInternal: %s", error);
} }
if (error_code != CELL_OK) if (error_code != CELL_OK)
@@ -606,7 +611,7 @@ namespace np
{ {
case rpcn::ErrorType::NoError: break; case rpcn::ErrorType::NoError: break;
case rpcn::ErrorType::RoomMissing: error_code = SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_ROOM; break; case rpcn::ErrorType::RoomMissing: error_code = SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_ROOM; break;
default: fmt::throw_exception("Unexpected error in reply to GetRoomDataInternal: %d", static_cast<u8>(error)); default: fmt::throw_exception("Unexpected error in reply to SetRoomDataInternal: %s", error);
} }
cb_info_opt->queue_callback(req_id, 0, error_code, 0); cb_info_opt->queue_callback(req_id, 0, error_code, 0);
@@ -640,7 +645,7 @@ namespace np
case rpcn::ErrorType::NoError: break; case rpcn::ErrorType::NoError: break;
case rpcn::ErrorType::RoomMissing: error_code = SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_ROOM; break; case rpcn::ErrorType::RoomMissing: error_code = SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_ROOM; break;
case rpcn::ErrorType::NotFound: error_code = SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_USER; break; case rpcn::ErrorType::NotFound: error_code = SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_USER; break;
default: fmt::throw_exception("Unexpected error in reply to GetRoomMemberDataInternal: %d", static_cast<u8>(error)); default: fmt::throw_exception("Unexpected error in reply to GetRoomMemberDataInternal: %s", error);
} }
if (error_code != CELL_OK) if (error_code != CELL_OK)
@@ -694,7 +699,7 @@ namespace np
case rpcn::ErrorType::RoomMissing: error_code = SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_ROOM; break; case rpcn::ErrorType::RoomMissing: error_code = SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_ROOM; break;
case rpcn::ErrorType::NotFound: error_code = SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_USER; break; case rpcn::ErrorType::NotFound: error_code = SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_USER; break;
case rpcn::ErrorType::Unauthorized: error_code = SCE_NP_MATCHING2_SERVER_ERROR_FORBIDDEN; break; case rpcn::ErrorType::Unauthorized: error_code = SCE_NP_MATCHING2_SERVER_ERROR_FORBIDDEN; break;
default: fmt::throw_exception("Unexpected error in reply to SetRoomMemberDataInternal: %d", static_cast<u8>(error)); default: fmt::throw_exception("Unexpected error in reply to SetRoomMemberDataInternal: %s", error);
} }
cb_info_opt->queue_callback(req_id, 0, error_code, 0); cb_info_opt->queue_callback(req_id, 0, error_code, 0);
@@ -723,7 +728,7 @@ namespace np
switch (error) switch (error)
{ {
case rpcn::ErrorType::NoError: break; case rpcn::ErrorType::NoError: break;
default: fmt::throw_exception("Unexpected error in reply to SetUserInfo: %d", static_cast<u8>(error)); default: fmt::throw_exception("Unexpected error in reply to SetUserInfo: %s", error);
} }
cb_info_opt->queue_callback(req_id, 0, 0, 0); cb_info_opt->queue_callback(req_id, 0, 0, 0);
@@ -755,7 +760,7 @@ namespace np
{ {
case rpcn::ErrorType::NoError: break; case rpcn::ErrorType::NoError: break;
case rpcn::ErrorType::RoomMissing: error_code = SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_ROOM; break; case rpcn::ErrorType::RoomMissing: error_code = SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_ROOM; break;
default: fmt::throw_exception("Unexpected error in reply to PingRoomOwner: %d", static_cast<u8>(error)); default: fmt::throw_exception("Unexpected error in reply to PingRoomOwner: %s", error);
} }
if (error_code != CELL_OK) if (error_code != CELL_OK)
@@ -803,7 +808,7 @@ namespace np
case rpcn::ErrorType::NoError: break; case rpcn::ErrorType::NoError: break;
case rpcn::ErrorType::RoomMissing: error_code = SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_ROOM; break; case rpcn::ErrorType::RoomMissing: error_code = SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_ROOM; break;
case rpcn::ErrorType::Unauthorized: error_code = SCE_NP_MATCHING2_SERVER_ERROR_FORBIDDEN; break; case rpcn::ErrorType::Unauthorized: error_code = SCE_NP_MATCHING2_SERVER_ERROR_FORBIDDEN; break;
default: fmt::throw_exception("Unexpected error in reply to SendRoomMessage: %d", static_cast<u8>(error)); default: fmt::throw_exception("Unexpected error in reply to SendRoomMessage: %s", error);
} }
cb_info_opt->queue_callback(req_id, 0, error_code, 0); cb_info_opt->queue_callback(req_id, 0, error_code, 0);
@@ -841,7 +846,7 @@ namespace np
rpcn_log.error("Signaling information was requested for a user that doesn't exist or is not online"); rpcn_log.error("Signaling information was requested for a user that doesn't exist or is not online");
return; return;
} }
default: fmt::throw_exception("Unexpected error in reply to RequestSignalingInfos: %d", static_cast<u8>(error)); default: fmt::throw_exception("Unexpected error in reply to RequestSignalingInfos: %s", error);
} }
const auto resp = reply.get_protobuf<np2_structs::SignalingAddr>(); const auto resp = reply.get_protobuf<np2_structs::SignalingAddr>();
@@ -861,9 +866,7 @@ namespace np
const u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_GetLobbyInfoList, false); const u32 req_id = generate_callback_info(ctx_id, optParam, SCE_NP_MATCHING2_REQUEST_EVENT_GetLobbyInfoList, false);
auto cb_info_opt = take_pending_request(req_id); auto cb_info_opt = take_pending_request(req_id);
ensure (cb_info_opt);
if (!cb_info_opt)
return true;
const u32 event_key = get_event_key(); const u32 event_key = get_event_key();
@@ -1017,7 +1020,7 @@ namespace np
{ {
case rpcn::ErrorType::NoError: break; case rpcn::ErrorType::NoError: break;
case rpcn::ErrorType::NotFound: error_code = SCE_NP_COMMUNITY_SERVER_ERROR_RANKING_BOARD_MASTER_NOT_FOUND; break; case rpcn::ErrorType::NotFound: error_code = SCE_NP_COMMUNITY_SERVER_ERROR_RANKING_BOARD_MASTER_NOT_FOUND; break;
default: fmt::throw_exception("Unexpected error in reply to GetBoardInfos: %d", static_cast<u8>(error)); default: fmt::throw_exception("Unexpected error in reply to GetBoardInfos: %s", error);
} }
if (error_code != CELL_OK) if (error_code != CELL_OK)
@@ -1091,7 +1094,7 @@ namespace np
score_trans->wake_cond.notify_one(); score_trans->wake_cond.notify_one();
return; return;
} }
default: fmt::throw_exception("Unexpected error in reply_record_score: %d", static_cast<u8>(error)); default: fmt::throw_exception("Unexpected error in reply_record_score: %s", error);
} }
auto tmp_rank = reply.get<u32>(); auto tmp_rank = reply.get<u32>();
@@ -1154,7 +1157,7 @@ namespace np
case rpcn::ErrorType::NotFound: trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_RANKING_STORE_NOT_FOUND); break; case rpcn::ErrorType::NotFound: trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_RANKING_STORE_NOT_FOUND); break;
case rpcn::ErrorType::ScoreInvalid: trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_INVALID_SCORE); break; case rpcn::ErrorType::ScoreInvalid: trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_INVALID_SCORE); break;
case rpcn::ErrorType::ScoreHasData: trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_GAME_DATA_ALREADY_EXISTS); break; case rpcn::ErrorType::ScoreHasData: trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_GAME_DATA_ALREADY_EXISTS); break;
default: fmt::throw_exception("Unexpected error in reply to RecordScoreData: %d", static_cast<u8>(error)); default: fmt::throw_exception("Unexpected error in reply to RecordScoreData: %s", error);
} }
} }
@@ -1207,7 +1210,7 @@ namespace np
{ {
case rpcn::ErrorType::NoError: break; case rpcn::ErrorType::NoError: break;
case rpcn::ErrorType::NotFound: score_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_RANKING_GAME_DATA_MASTER_NOT_FOUND); return; case rpcn::ErrorType::NotFound: score_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_RANKING_GAME_DATA_MASTER_NOT_FOUND); return;
default: fmt::throw_exception("Unexpected error in reply to GetScoreData: %d", static_cast<u8>(error)); default: fmt::throw_exception("Unexpected error in reply to GetScoreData: %s", error);
} }
auto* tdata = std::get_if<tdata_get_score_data>(&score_trans->tdata); auto* tdata = std::get_if<tdata_get_score_data>(&score_trans->tdata);
@@ -1287,7 +1290,7 @@ namespace np
switch (error) switch (error)
{ {
case rpcn::ErrorType::NoError: break; case rpcn::ErrorType::NoError: break;
default: fmt::throw_exception("Unexpected error in GetScoreResponse: %d", static_cast<u8>(error)); default: fmt::throw_exception("Unexpected error in GetScoreResponse: %s", error);
} }
const auto resp = reply.get_protobuf<np2_structs::GetScoreResponse>(); const auto resp = reply.get_protobuf<np2_structs::GetScoreResponse>();
@@ -1476,7 +1479,7 @@ namespace np
case rpcn::ErrorType::NotFound: trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_USER_NOT_ASSIGNED); break; case rpcn::ErrorType::NotFound: trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_USER_NOT_ASSIGNED); break;
case rpcn::ErrorType::Unauthorized: trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_FORBIDDEN); break; case rpcn::ErrorType::Unauthorized: trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_FORBIDDEN); break;
case rpcn::ErrorType::CondFail: trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_CONDITIONS_NOT_SATISFIED); break; case rpcn::ErrorType::CondFail: trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_CONDITIONS_NOT_SATISFIED); break;
default: fmt::throw_exception("Unexpected error in handle_tus_no_data: %d", static_cast<u8>(error)); default: fmt::throw_exception("Unexpected error in handle_tus_no_data: %s", error);
} }
} }
@@ -1499,7 +1502,7 @@ namespace np
case rpcn::ErrorType::NotFound: return tus_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_USER_NOT_ASSIGNED); case rpcn::ErrorType::NotFound: return tus_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_USER_NOT_ASSIGNED);
case rpcn::ErrorType::Unauthorized: return tus_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_FORBIDDEN); case rpcn::ErrorType::Unauthorized: return tus_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_FORBIDDEN);
case rpcn::ErrorType::CondFail: return tus_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_CONDITIONS_NOT_SATISFIED); case rpcn::ErrorType::CondFail: return tus_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_CONDITIONS_NOT_SATISFIED);
default: fmt::throw_exception("Unexpected error in handle_TusVarResponse: %d", static_cast<u8>(error)); default: fmt::throw_exception("Unexpected error in handle_TusVarResponse: %s", error);
} }
const auto resp = reply.get_protobuf<np2_structs::TusVarResponse>(); const auto resp = reply.get_protobuf<np2_structs::TusVarResponse>();
@@ -1555,7 +1558,7 @@ namespace np
case rpcn::ErrorType::NotFound: return tus_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_USER_NOT_ASSIGNED); case rpcn::ErrorType::NotFound: return tus_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_USER_NOT_ASSIGNED);
case rpcn::ErrorType::Unauthorized: return tus_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_FORBIDDEN); case rpcn::ErrorType::Unauthorized: return tus_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_FORBIDDEN);
case rpcn::ErrorType::CondFail: return tus_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_CONDITIONS_NOT_SATISFIED); case rpcn::ErrorType::CondFail: return tus_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_CONDITIONS_NOT_SATISFIED);
default: fmt::throw_exception("Unexpected error in handle_TusVariable: %d", static_cast<u8>(error)); default: fmt::throw_exception("Unexpected error in handle_TusVariable: %s", error);
} }
auto pb_var = reply.get_protobuf<np2_structs::TusVariable>(); auto pb_var = reply.get_protobuf<np2_structs::TusVariable>();
@@ -1603,7 +1606,7 @@ namespace np
case rpcn::ErrorType::NotFound: return tus_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_USER_NOT_ASSIGNED); case rpcn::ErrorType::NotFound: return tus_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_USER_NOT_ASSIGNED);
case rpcn::ErrorType::Unauthorized: return tus_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_FORBIDDEN); case rpcn::ErrorType::Unauthorized: return tus_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_FORBIDDEN);
case rpcn::ErrorType::CondFail: return tus_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_CONDITIONS_NOT_SATISFIED); case rpcn::ErrorType::CondFail: return tus_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_CONDITIONS_NOT_SATISFIED);
default: fmt::throw_exception("Unexpected error in handle_TusDataStatusResponse: %d", static_cast<u8>(error)); default: fmt::throw_exception("Unexpected error in handle_TusDataStatusResponse: %s", error);
} }
const auto resp = reply.get_protobuf<np2_structs::TusDataStatusResponse>(); const auto resp = reply.get_protobuf<np2_structs::TusDataStatusResponse>();
@@ -1803,7 +1806,7 @@ namespace np
if (!tdata) if (!tdata)
{ {
trans_ctx->tdata = tdata_tus_get_data{.recvSize = recvSize, .dataStatus = dataStatus, .data = data}; trans_ctx->tdata = tdata_tus_get_data{.recvSize = recvSize, .dataStatus = dataStatus, .data = data};
const u32 req_id = get_req_id(REQUEST_ID_HIGH::SCORE); const u32 req_id = get_req_id(REQUEST_ID_HIGH::TUS);
get_rpcn()->tus_get_data(req_id, trans_ctx->communicationId, targetNpId, slotId, vuser); get_rpcn()->tus_get_data(req_id, trans_ctx->communicationId, targetNpId, slotId, vuser);
transaction_async_handler(std::move(lock), trans_ctx, req_id, async); transaction_async_handler(std::move(lock), trans_ctx, req_id, async);
return; return;
@@ -1844,7 +1847,7 @@ namespace np
case rpcn::ErrorType::NotFound: return tus_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_USER_NOT_ASSIGNED); case rpcn::ErrorType::NotFound: return tus_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_USER_NOT_ASSIGNED);
case rpcn::ErrorType::Unauthorized: return tus_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_FORBIDDEN); case rpcn::ErrorType::Unauthorized: return tus_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_FORBIDDEN);
case rpcn::ErrorType::CondFail: return tus_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_CONDITIONS_NOT_SATISFIED); case rpcn::ErrorType::CondFail: return tus_trans->set_result_and_wake(SCE_NP_COMMUNITY_SERVER_ERROR_CONDITIONS_NOT_SATISFIED);
default: fmt::throw_exception("Unexpected error in reply to TusGetData: %d", static_cast<u8>(error)); default: fmt::throw_exception("Unexpected error in reply to TusGetData: %s", error);
} }
auto pb_data = reply.get_protobuf<np2_structs::TusData>(); auto pb_data = reply.get_protobuf<np2_structs::TusData>();
@@ -1870,6 +1873,7 @@ namespace np
data_status->data = tdata->data; data_status->data = tdata->data;
data_status->dataSize = ::narrow<u32>(pb_data->data().size()); data_status->dataSize = ::narrow<u32>(pb_data->data().size());
data_status->info.infoSize = ::narrow<u32>(pb_status.info().size()); data_status->info.infoSize = ::narrow<u32>(pb_status.info().size());
memcpy(data_status->info.data, pb_data->status().info().data(), std::min(pb_data->status().info().size(), sizeof(data_status->info.data)));
const u32 to_copy = std::min<u32>(data_status->dataSize, tdata->recvSize); const u32 to_copy = std::min<u32>(data_status->dataSize, tdata->recvSize);
memcpy(data, pb_data->data().data(), to_copy); memcpy(data, pb_data->data().data(), to_copy);
+21 -6
View File
@@ -303,7 +303,11 @@ namespace np
gui_cache.del_room(room_status->id); gui_cache.del_room(room_status->id);
gui_notifications.list.emplace(std::make_pair(gui_notifications.current_gui_ctx_id, req_id), gui_notification{.event = SCE_NP_MATCHING_EVENT_LEAVE_ROOM_DONE, .edata = std::move(edata)}); {
std::lock_guard lock(gui_notifications.mutex);
gui_notifications.list.emplace(std::make_pair(gui_notifications.current_gui_ctx_id, req_id), gui_notification{.event = SCE_NP_MATCHING_EVENT_LEAVE_ROOM_DONE, .edata = std::move(edata)});
}
ctx->queue_callback(req_id, SCE_NP_MATCHING_EVENT_LEAVE_ROOM_DONE, 0); ctx->queue_callback(req_id, SCE_NP_MATCHING_EVENT_LEAVE_ROOM_DONE, 0);
} }
@@ -453,7 +457,11 @@ namespace np
extra_nps::print_SceNpMatchingRoom(room_info); extra_nps::print_SceNpMatchingRoom(room_info);
gui_notifications.list.emplace(std::make_pair(gui_notifications.current_gui_ctx_id, req_id), gui_notification{.event = SCE_NP_MATCHING_EVENT_GET_ROOM_SEARCH_FLAG_DONE, .edata = std::move(edata)}); {
std::lock_guard lock(gui_notifications.mutex);
gui_notifications.list.emplace(std::make_pair(gui_notifications.current_gui_ctx_id, req_id), gui_notification{.event = SCE_NP_MATCHING_EVENT_GET_ROOM_SEARCH_FLAG_DONE, .edata = std::move(edata)});
}
ctx->queue_callback(req_id, SCE_NP_MATCHING_EVENT_GET_ROOM_SEARCH_FLAG_DONE, 0); ctx->queue_callback(req_id, SCE_NP_MATCHING_EVENT_GET_ROOM_SEARCH_FLAG_DONE, 0);
} }
@@ -548,7 +556,11 @@ namespace np
extra_nps::print_SceNpMatchingRoom(room_info); extra_nps::print_SceNpMatchingRoom(room_info);
gui_notifications.list.emplace(std::make_pair(gui_notifications.current_gui_ctx_id, req_id), gui_notification{.event = SCE_NP_MATCHING_EVENT_GET_ROOM_INFO_DONE, .edata = std::move(edata)}); {
std::lock_guard lock(gui_notifications.mutex);
gui_notifications.list.emplace(std::make_pair(gui_notifications.current_gui_ctx_id, req_id), gui_notification{.event = SCE_NP_MATCHING_EVENT_GET_ROOM_INFO_DONE, .edata = std::move(edata)});
}
ctx->queue_callback(req_id, SCE_NP_MATCHING_EVENT_GET_ROOM_INFO_DONE, 0); ctx->queue_callback(req_id, SCE_NP_MATCHING_EVENT_GET_ROOM_INFO_DONE, 0);
} }
@@ -581,9 +593,13 @@ namespace np
SceNpRoomId room_id{}; SceNpRoomId room_id{};
ensure(!resp->id().empty() && resp->id().size() == sizeof(SceNpRoomId::opt)); ensure(!resp->id().empty() && resp->id().size() == sizeof(SceNpRoomId::opt));
ctx->wakey = 0;
std::memcpy(room_id.opt, resp->id().data(), sizeof(SceNpRoomId::opt)); std::memcpy(room_id.opt, resp->id().data(), sizeof(SceNpRoomId::opt));
const auto [_, inserted] = pending_quickmatching.insert_or_assign(room_id, ctx->ctx_id); {
ensure(inserted); std::lock_guard lock(this->mutex_quickmatching);
const auto [_, inserted] = pending_quickmatching.insert_or_assign(room_id, ctx->ctx_id);
ensure(inserted);
}
// Now that the reply has been received, we start the wait for the notification // Now that the reply has been received, we start the wait for the notification
ctx->thread = std::make_unique<named_thread<std::function<void(SceNpRoomId)>>>("NP GUI Timeout Worker", [ctx, req_id, this](SceNpRoomId room_id) ctx->thread = std::make_unique<named_thread<std::function<void(SceNpRoomId)>>>("NP GUI Timeout Worker", [ctx, req_id, this](SceNpRoomId room_id)
@@ -615,7 +631,6 @@ namespace np
} }
}); });
ctx->wakey = 0;
auto& thread = *ctx->thread; auto& thread = *ctx->thread;
thread(room_id); thread(room_id);
} }
+2 -2
View File
@@ -1489,7 +1489,7 @@ namespace rpcn
if (error == ErrorType::NoError) if (error == ErrorType::NoError)
rpcn_log.success("add_friend(\"%s\") succeeded", friend_username); rpcn_log.success("add_friend(\"%s\") succeeded", friend_username);
else else
rpcn_log.error("add_friend(\"%s\") failed with error: %s", error); rpcn_log.error("add_friend(\"%s\") failed with error: %s", friend_username, error);
return error; return error;
} }
@@ -3085,7 +3085,7 @@ namespace rpcn
} }
case NotificationType::FriendPresenceChanged: case NotificationType::FriendPresenceChanged:
{ {
const std::string username = vdata.get_string(true); const std::string username = vdata.get_string(false);
SceNpCommunicationId pr_com_id = vdata.get_com_id(); SceNpCommunicationId pr_com_id = vdata.get_com_id();
std::string pr_title = fmt::truncate(vdata.get_string(true), SCE_NP_BASIC_PRESENCE_TITLE_SIZE_MAX - 1); std::string pr_title = fmt::truncate(vdata.get_string(true), SCE_NP_BASIC_PRESENCE_TITLE_SIZE_MAX - 1);
std::string pr_status = fmt::truncate(vdata.get_string(true), SCE_NP_BASIC_PRESENCE_EXTENDED_STATUS_SIZE_MAX - 1); std::string pr_status = fmt::truncate(vdata.get_string(true), SCE_NP_BASIC_PRESENCE_EXTENDED_STATUS_SIZE_MAX - 1);
+1
View File
@@ -774,6 +774,7 @@ void signaling_handler::send_information_packets(u32 addr, u16 port, const SceNp
auto& sent_packet = sig_packet; auto& sent_packet = sig_packet;
sent_packet.command = signal_info; sent_packet.command = signal_info;
retire_packet(si, signal_info);
send_signaling_packet(sent_packet, addr, port); send_signaling_packet(sent_packet, addr, port);
queue_signaling_packet(sent_packet, si, steady_clock::now() + REPEAT_INFO_DELAY); queue_signaling_packet(sent_packet, si, steady_clock::now() + REPEAT_INFO_DELAY);
wake_up(); wake_up();
+1 -1
View File
@@ -133,7 +133,7 @@ private:
signaling_packet sig_packet{}; signaling_packet sig_packet{};
std::map<steady_clock::time_point, queued_packet> qpackets; // (wakeup time, packet) std::multimap<steady_clock::time_point, queued_packet> qpackets; // (wakeup time, packet)
u32 cur_conn_id = 1; u32 cur_conn_id = 1;
std::unordered_map<std::string, u32> npid_to_conn_id; // (npid, conn_id) std::unordered_map<std::string, u32> npid_to_conn_id; // (npid, conn_id)
+19 -16
View File
@@ -89,12 +89,10 @@ void upnp_handler::upnp_enable()
if (desc_xml) if (desc_xml)
{ {
IGDdatas igd_data{}; parserootdesc(desc_xml, desc_xml_size, &m_igd_data);
UPNPUrls igd_urls{};
parserootdesc(desc_xml, desc_xml_size, &igd_data);
free(desc_xml); free(desc_xml);
desc_xml = nullptr; desc_xml = nullptr;
GetUPNPUrls(&igd_urls, &igd_data, dev->descURL, 1); GetUPNPUrls(&m_igd_urls, &m_igd_data, dev->descURL, 1);
upnp_log.notice("Found UPnP device type:%s at %s", dev->st, dev->descURL); upnp_log.notice("Found UPnP device type:%s at %s", dev->st, dev->descURL);
@@ -116,24 +114,28 @@ void upnp_handler::upnp_enable()
freeUPNPDevlist(devlist); freeUPNPDevlist(devlist);
} }
void upnp_handler::add_port_redir(std::string_view addr, u16 internal_port, std::string_view protocol) void upnp_handler::add_port_redir(const std::string& addr, u16 internal_port, std::string_view protocol)
{ {
if (!m_active) if (!m_active)
return; return;
std::lock_guard lock(m_mutex); std::lock_guard lock(m_mutex);
u16 external_port = internal_port; if (m_bindings[std::string(protocol)].contains(internal_port))
std::string internal_port_str = fmt::format("%d", internal_port); return;
const std::string internal_port_str = fmt::format("%d", internal_port);
const std::string protocol_str(protocol);
const u32 max_port = std::min(static_cast<u32>(internal_port) + 100, 0xFFFFu);
int res = 0; int res = 0;
for (u16 external_port = internal_port; external_port < internal_port + 100; external_port++) for (u32 external_port = internal_port; external_port <= max_port; external_port++)
{ {
std::string external_port_str = fmt::format("%d", external_port); std::string external_port_str = fmt::format("%d", external_port);
res = UPNP_AddPortMapping(m_igd_urls.controlURL, m_igd_data.first.servicetype, external_port_str.c_str(), internal_port_str.c_str(), addr.data(), "RPCS3", protocol.data(), nullptr, nullptr); res = UPNP_AddPortMapping(m_igd_urls.controlURL, m_igd_data.first.servicetype, external_port_str.c_str(), internal_port_str.c_str(), addr.c_str(), "RPCS3", protocol_str.c_str(), nullptr, nullptr);
if (res == UPNPCOMMAND_SUCCESS) if (res == UPNPCOMMAND_SUCCESS)
{ {
m_bindings[std::string(protocol)][internal_port] = external_port; m_bindings[protocol_str][static_cast<u16>(internal_port)] = external_port;
upnp_log.notice("Successfully bound %s:%d(%s) to IGD:%d", addr, internal_port, protocol, external_port); upnp_log.notice("Successfully bound %s:%d(%s) to IGD:%d", addr, internal_port, protocol, external_port);
return; return;
} }
@@ -146,7 +148,7 @@ void upnp_handler::add_port_redir(std::string_view addr, u16 internal_port, std:
// } // }
} }
upnp_log.error("Failed to bind %s:%d(%s) to IGD:(%d=>%d): %d", addr, internal_port, protocol, internal_port, external_port, res); upnp_log.error("Failed to bind %s:%d(%s) to IGD:(%d=>%d): %d", addr, internal_port, protocol, internal_port, internal_port, res);
} }
void upnp_handler::remove_port_redir(u16 internal_port, std::string_view protocol) void upnp_handler::remove_port_redir(u16 internal_port, std::string_view protocol)
@@ -156,27 +158,28 @@ void upnp_handler::remove_port_redir(u16 internal_port, std::string_view protoco
std::lock_guard lock(m_mutex); std::lock_guard lock(m_mutex);
const std::string str_protocol(protocol); const std::string protocol_str(protocol);
if (!m_bindings.contains(str_protocol) || !::at32(m_bindings, str_protocol).contains(internal_port)) if (!m_bindings.contains(protocol_str) || !::at32(m_bindings, protocol_str).contains(internal_port))
{ {
upnp_log.error("tried to unbind port mapping %d to IGD(%s) but it isn't bound", internal_port, protocol); upnp_log.error("tried to unbind port mapping %d to IGD(%s) but it isn't bound", internal_port, protocol);
return; return;
} }
const u16 external_port = ::at32(::at32(m_bindings, str_protocol), internal_port); const u16 external_port = ::at32(::at32(m_bindings, protocol_str), internal_port);
remove_port_redir_external(external_port, protocol); remove_port_redir_external(external_port, protocol);
ensure(::at32(m_bindings, str_protocol).erase(internal_port)); ensure(::at32(m_bindings, protocol_str).erase(internal_port));
upnp_log.notice("Successfully deleted port mapping %d to IGD:%d(%s)", internal_port, external_port, protocol); upnp_log.notice("Successfully deleted port mapping %d to IGD:%d(%s)", internal_port, external_port, protocol);
} }
void upnp_handler::remove_port_redir_external(u16 external_port, std::string_view protocol, bool verbose) void upnp_handler::remove_port_redir_external(u16 external_port, std::string_view protocol, bool verbose)
{ {
const std::string str_ext_port = fmt::format("%d", external_port); const std::string str_ext_port = fmt::format("%d", external_port);
const std::string protocol_str(protocol);
if (int res = UPNP_DeletePortMapping(m_igd_urls.controlURL, m_igd_data.first.servicetype, str_ext_port.c_str(), protocol.data(), nullptr); res != 0 && verbose) if (int res = UPNP_DeletePortMapping(m_igd_urls.controlURL, m_igd_data.first.servicetype, str_ext_port.c_str(), protocol_str.c_str(), nullptr); res != 0 && verbose)
upnp_log.error("Failed to delete port mapping IGD:%s(%s): %d", str_ext_port, protocol, res); upnp_log.error("Failed to delete port mapping IGD:%s(%s): %d", str_ext_port, protocol, res);
} }
+1 -1
View File
@@ -13,7 +13,7 @@ public:
~upnp_handler(); ~upnp_handler();
void upnp_enable(); void upnp_enable();
void add_port_redir(std::string_view addr, u16 internal_port, std::string_view protocol); void add_port_redir(const std::string& addr, u16 internal_port, std::string_view protocol);
void remove_port_redir(u16 internal_port, std::string_view protocol); void remove_port_redir(u16 internal_port, std::string_view protocol);
bool is_active() const; bool is_active() const;