mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-21 18:22:33 +01:00
RPCN v0.6
This commit is contained in:
parent
67c02e3522
commit
eea73deab3
2
3rdparty/flatbuffers
vendored
2
3rdparty/flatbuffers
vendored
@ -1 +1 @@
|
||||
Subproject commit 615616cb5549a34bdf288c04bc1b94bd7a65c396
|
||||
Subproject commit 06c5c7ed0bd987a918cf88caafb094f22cdd1721
|
3
3rdparty/wolfssl/CMakeLists.txt
vendored
3
3rdparty/wolfssl/CMakeLists.txt
vendored
@ -5,9 +5,10 @@ if(USE_SYSTEM_WOLFSSL)
|
||||
target_link_libraries(wolfssl INTERFACE PkgConfig::WolfSSL)
|
||||
else()
|
||||
# TODO(cjj19970505@live.cn)
|
||||
# OPENSSL_EXTRA, WOLFSSL_DES_ECB and HAVE_SNI are unconfigurable from CMake cache.
|
||||
# OPENSSL_EXTRA, and HAVE_SNI are unconfigurable from CMake cache.
|
||||
# but they do have it in a TODO list (wolfssl/CMakeList, 1021)
|
||||
add_compile_definitions(OPENSSL_EXTRA WOLFSSL_DES_ECB HAVE_SNI HAVE_WRITE_DUP)
|
||||
add_compile_definitions(FP_MAX_BITS=8192)
|
||||
|
||||
set(WOLFSSL_TLS13 "no" CACHE INTERNAL "")
|
||||
set(WOLFSSL_SHA224 "yes" CACHE INTERNAL "")
|
||||
|
@ -237,7 +237,7 @@ struct netstart_hack
|
||||
|
||||
error_code cellNetCtlNetStartDialogLoadAsync(vm::cptr<CellNetCtlNetStartDialogParam> param)
|
||||
{
|
||||
cellNetCtl.error("cellNetCtlNetStartDialogLoadAsync(param=*0x%x)", param);
|
||||
cellNetCtl.warning("cellNetCtlNetStartDialogLoadAsync(param=*0x%x)", param);
|
||||
|
||||
auto& nph = g_fxo->get<named_thread<np::np_handler>>();
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1393,14 +1393,14 @@ struct SceNpMatchingReqRange
|
||||
|
||||
struct SceNpScoreVariableSizeGameInfo
|
||||
{
|
||||
be_t<u64> infoSize;
|
||||
be_t<u32> infoSize;
|
||||
u8 data[SCE_NP_SCORE_VARIABLE_SIZE_GAMEINFO_MAXSIZE];
|
||||
u8 pad[3];
|
||||
};
|
||||
|
||||
struct SceNpScoreRecordOptParam
|
||||
{
|
||||
be_t<u64> size;
|
||||
be_t<u32> size;
|
||||
vm::bptr<SceNpScoreVariableSizeGameInfo> vsInfo;
|
||||
vm::bptr<CellRtcTick> reserved;
|
||||
};
|
||||
|
@ -319,7 +319,7 @@ error_code sceNpMatching2Term2()
|
||||
|
||||
error_code sceNpMatching2DestroyContext(SceNpMatching2ContextId ctxId)
|
||||
{
|
||||
sceNp2.todo("sceNpMatching2DestroyContext(ctxId=%d)", ctxId);
|
||||
sceNp2.warning("sceNpMatching2DestroyContext(ctxId=%d)", ctxId);
|
||||
|
||||
auto& nph = g_fxo->get<named_thread<np::np_handler>>();
|
||||
|
||||
@ -611,11 +611,20 @@ error_code sceNpMatching2SignalingGetConnectionInfo(
|
||||
return SCE_NP_MATCHING2_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
if (!connInfo)
|
||||
{
|
||||
return SCE_NP_MATCHING2_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
auto& sigh = g_fxo->get<named_thread<signaling_handler>>();
|
||||
const auto si = sigh.get_sig2_infos(roomId, memberId);
|
||||
|
||||
switch (code)
|
||||
{
|
||||
case SCE_NP_SIGNALING_CONN_INFO_RTT:
|
||||
{
|
||||
connInfo->rtt = 20000; // HACK
|
||||
connInfo->rtt = si.rtt;
|
||||
sceNp2.warning("Returning a RTT of %d microseconds", connInfo->rtt);
|
||||
break;
|
||||
}
|
||||
case SCE_NP_SIGNALING_CONN_INFO_BANDWIDTH:
|
||||
@ -625,22 +634,17 @@ error_code sceNpMatching2SignalingGetConnectionInfo(
|
||||
}
|
||||
case SCE_NP_SIGNALING_CONN_INFO_PEER_NPID:
|
||||
{
|
||||
// TODO: need an update to whole signaling as matching2 signaling ignores npids atm
|
||||
sceNp2.fatal("sceNpMatching2SignalingGetConnectionInfo Unimplemented SCE_NP_SIGNALING_CONN_INFO_PEER_NPID");
|
||||
connInfo->npId = si.npid;
|
||||
break;
|
||||
}
|
||||
case SCE_NP_SIGNALING_CONN_INFO_PEER_ADDRESS:
|
||||
{
|
||||
auto& sigh = g_fxo->get<named_thread<signaling_handler>>();
|
||||
const auto si = sigh.get_sig2_infos(roomId, memberId);
|
||||
connInfo->address.port = std::bit_cast<u16, be_t<u16>>(si.port);
|
||||
connInfo->address.addr.np_s_addr = si.addr;
|
||||
break;
|
||||
}
|
||||
case SCE_NP_SIGNALING_CONN_INFO_MAPPED_ADDRESS:
|
||||
{
|
||||
auto& sigh = g_fxo->get<named_thread<signaling_handler>>();
|
||||
const auto si = sigh.get_sig2_infos(roomId, memberId);
|
||||
connInfo->address.port = std::bit_cast<u16, be_t<u16>>(si.mapped_port);
|
||||
connInfo->address.addr.np_s_addr = si.mapped_addr;
|
||||
break;
|
||||
@ -652,8 +656,7 @@ error_code sceNpMatching2SignalingGetConnectionInfo(
|
||||
}
|
||||
default:
|
||||
{
|
||||
sceNp2.fatal("sceNpMatching2SignalingGetConnectionInfo Unimplemented code: %d", code);
|
||||
return CELL_OK;
|
||||
return SCE_NP_MATCHING2_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
}
|
||||
|
||||
@ -715,6 +718,16 @@ error_code sceNpMatching2AbortRequest(SceNpMatching2ContextId ctxId, SceNpMatchi
|
||||
return SCE_NP_MATCHING2_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
if (!ctxId)
|
||||
{
|
||||
return SCE_NP_MATCHING2_ERROR_INVALID_CONTEXT_ID;
|
||||
}
|
||||
|
||||
if (!check_match2_context(ctxId))
|
||||
{
|
||||
return SCE_NP_MATCHING2_ERROR_CONTEXT_NOT_FOUND;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@ -1349,7 +1362,7 @@ error_code sceNpMatching2SetDefaultRequestOptParam(SceNpMatching2ContextId ctxId
|
||||
|
||||
error_code sceNpMatching2RegisterRoomEventCallback(SceNpMatching2ContextId ctxId, vm::ptr<SceNpMatching2RoomEventCallback> cbFunc, vm::ptr<void> cbFuncArg)
|
||||
{
|
||||
sceNp2.todo("sceNpMatching2RegisterRoomEventCallback(ctxId=%d, cbFunc=*0x%x, cbFuncArg=*0x%x)", ctxId, cbFunc, cbFuncArg);
|
||||
sceNp2.warning("sceNpMatching2RegisterRoomEventCallback(ctxId=%d, cbFunc=*0x%x, cbFuncArg=*0x%x)", ctxId, cbFunc, cbFuncArg);
|
||||
|
||||
auto& nph = g_fxo->get<named_thread<np::np_handler>>();
|
||||
|
||||
@ -1546,7 +1559,7 @@ error_code sceNpMatching2SetLobbyMemberDataInternal(
|
||||
|
||||
error_code sceNpMatching2RegisterRoomMessageCallback(SceNpMatching2ContextId ctxId, vm::ptr<SceNpMatching2RoomMessageCallback> cbFunc, vm::ptr<void> cbFuncArg)
|
||||
{
|
||||
sceNp2.todo("sceNpMatching2RegisterRoomMessageCallback(ctxId=%d, cbFunc=*0x%x, cbFuncArg=*0x%x)", ctxId, cbFunc, cbFuncArg);
|
||||
sceNp2.warning("sceNpMatching2RegisterRoomMessageCallback(ctxId=%d, cbFunc=*0x%x, cbFuncArg=*0x%x)", ctxId, cbFunc, cbFuncArg);
|
||||
|
||||
auto& nph = g_fxo->get<named_thread<np::np_handler>>();
|
||||
|
||||
|
@ -822,6 +822,7 @@ error_code sys_net_bnet_recvfrom(ppu_thread& ppu, s32 s, vm::ptr<void> buf, u32
|
||||
{
|
||||
sn_addr = res_addr;
|
||||
std::memcpy(buf.get_ptr(), vec.data(), res);
|
||||
sys_net_dump_data("recvfrom", vec.data(), res);
|
||||
}
|
||||
result = res;
|
||||
lv2_obj::awake(&ppu);
|
||||
@ -998,6 +999,8 @@ error_code sys_net_bnet_sendto(ppu_thread& ppu, s32 s, vm::cptr<void> buf, u32 l
|
||||
return -SYS_NET_EAFNOSUPPORT;
|
||||
}
|
||||
|
||||
sys_net_dump_data("sendto", static_cast<const u8 *>(buf.get_ptr()), len);
|
||||
|
||||
const std::optional<sys_net_sockaddr> sn_addr = addr ? std::optional<sys_net_sockaddr>(*addr) : std::nullopt;
|
||||
const std::vector<u8> buf_copy(vm::_ptr<const char>(buf.addr()), vm::_ptr<const char>(buf.addr()) + len);
|
||||
s32 result{};
|
||||
@ -1222,7 +1225,9 @@ error_code sys_net_bnet_close(ppu_thread& ppu, s32 s)
|
||||
}
|
||||
|
||||
if (sock->get_queue_size())
|
||||
sys_net.error("CLOSE");
|
||||
{
|
||||
sock->abort_socket(0);
|
||||
}
|
||||
|
||||
sock->close();
|
||||
|
||||
@ -1718,6 +1723,9 @@ error_code lv2_socket::abort_socket(s32 flags)
|
||||
|
||||
for (auto& [ppu, _] : qcopy)
|
||||
{
|
||||
if (!ppu)
|
||||
continue;
|
||||
|
||||
sys_net.warning("lv2_socket::abort_socket(): waking up \"%s\": (func: %s, r3=0x%x, r4=0x%x, r5=0x%x, r6=0x%x)", ppu->get_name(), ppu->current_function, ppu->gpr[3], ppu->gpr[4], ppu->gpr[5], ppu->gpr[6]);
|
||||
ppu->gpr[3] = static_cast<u64>(-SYS_NET_EINTR);
|
||||
lv2_obj::append(ppu.get());
|
||||
|
@ -204,7 +204,7 @@ s32 lv2_socket_p2p::setsockopt(s32 level, s32 optname, const std::vector<u8>& op
|
||||
return {};
|
||||
}
|
||||
|
||||
std::optional<std::tuple<s32, std::vector<u8>, sys_net_sockaddr>> lv2_socket_p2p::recvfrom([[maybe_unused]] s32 flags, u32 len, bool is_lock)
|
||||
std::optional<std::tuple<s32, std::vector<u8>, sys_net_sockaddr>> lv2_socket_p2p::recvfrom(s32 flags, u32 len, bool is_lock)
|
||||
{
|
||||
std::unique_lock<shared_mutex> lock(mutex, std::defer_lock);
|
||||
|
||||
@ -217,7 +217,10 @@ std::optional<std::tuple<s32, std::vector<u8>, sys_net_sockaddr>> lv2_socket_p2p
|
||||
|
||||
if (data.empty())
|
||||
{
|
||||
return {{-SYS_NET_EWOULDBLOCK, {}, {}}};
|
||||
if (so_nbio || (flags & SYS_NET_MSG_DONTWAIT))
|
||||
return {{-SYS_NET_EWOULDBLOCK, {}, {}}};
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::vector<u8> res_buf(len);
|
||||
|
@ -703,7 +703,7 @@ std::optional<std::tuple<s32, std::vector<u8>, sys_net_sockaddr>> lv2_socket_p2p
|
||||
|
||||
if (!data_available)
|
||||
{
|
||||
if (so_nbio)
|
||||
if (so_nbio || (flags & SYS_NET_MSG_DONTWAIT))
|
||||
{
|
||||
return {{-SYS_NET_EWOULDBLOCK, {}, {}}};
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "stdafx.h"
|
||||
#include "lv2_socket_raw.h"
|
||||
#include "Emu/NP/vport0.h"
|
||||
|
||||
LOG_CHANNEL(sys_net);
|
||||
|
||||
@ -20,7 +21,31 @@ void lv2_socket_raw::save(utils::serial& ar)
|
||||
|
||||
std::tuple<bool, s32, std::shared_ptr<lv2_socket>, sys_net_sockaddr> lv2_socket_raw::accept([[maybe_unused]] bool is_lock)
|
||||
{
|
||||
sys_net.todo("lv2_socket_raw::accept");
|
||||
sys_net.fatal("[RAW] accept() called on a RAW socket");
|
||||
return {};
|
||||
}
|
||||
|
||||
std::optional<s32> lv2_socket_raw::connect([[maybe_unused]] const sys_net_sockaddr& addr)
|
||||
{
|
||||
sys_net.fatal("[RAW] connect() called on a RAW socket");
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 lv2_socket_raw::connect_followup()
|
||||
{
|
||||
sys_net.fatal("[RAW] connect_followup() called on a RAW socket");
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
std::pair<s32, sys_net_sockaddr> lv2_socket_raw::getpeername()
|
||||
{
|
||||
sys_net.todo("[RAW] getpeername() called on a RAW socket");
|
||||
return {};
|
||||
}
|
||||
|
||||
s32 lv2_socket_raw::listen([[maybe_unused]] s32 backlog)
|
||||
{
|
||||
sys_net.todo("[RAW] listen() called on a RAW socket");
|
||||
return {};
|
||||
}
|
||||
|
||||
@ -30,24 +55,6 @@ s32 lv2_socket_raw::bind([[maybe_unused]] const sys_net_sockaddr& addr)
|
||||
return {};
|
||||
}
|
||||
|
||||
std::optional<s32> lv2_socket_raw::connect([[maybe_unused]] const sys_net_sockaddr& addr)
|
||||
{
|
||||
sys_net.todo("lv2_socket_raw::connect");
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 lv2_socket_raw::connect_followup()
|
||||
{
|
||||
sys_net.todo("lv2_socket_raw::connect_followup");
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
std::pair<s32, sys_net_sockaddr> lv2_socket_raw::getpeername()
|
||||
{
|
||||
sys_net.todo("lv2_socket_raw::getpeername");
|
||||
return {};
|
||||
}
|
||||
|
||||
std::pair<s32, sys_net_sockaddr> lv2_socket_raw::getsockname()
|
||||
{
|
||||
sys_net.todo("lv2_socket_raw::getsockname");
|
||||
@ -66,16 +73,10 @@ s32 lv2_socket_raw::setsockopt([[maybe_unused]] s32 level, [[maybe_unused]] s32
|
||||
return {};
|
||||
}
|
||||
|
||||
s32 lv2_socket_raw::listen([[maybe_unused]] s32 backlog)
|
||||
{
|
||||
sys_net.todo("lv2_socket_raw::listen");
|
||||
return {};
|
||||
}
|
||||
|
||||
std::optional<std::tuple<s32, std::vector<u8>, sys_net_sockaddr>> lv2_socket_raw::recvfrom([[maybe_unused]] s32 flags, [[maybe_unused]] u32 len, [[maybe_unused]] bool is_lock)
|
||||
{
|
||||
sys_net.todo("lv2_socket_raw::recvfrom");
|
||||
return {{{}, {}, {}}};
|
||||
return {};
|
||||
}
|
||||
|
||||
std::optional<s32> lv2_socket_raw::sendto([[maybe_unused]] s32 flags, [[maybe_unused]] const std::vector<u8>& buf, [[maybe_unused]] std::optional<sys_net_sockaddr> opt_sn_addr, [[maybe_unused]] bool is_lock)
|
||||
|
@ -53,9 +53,9 @@ std::vector<std::vector<u8>> get_rpcn_msgs()
|
||||
return msgs;
|
||||
}
|
||||
|
||||
std::vector<std::pair<std::pair<u32, u16>, std::vector<u8>>> get_sign_msgs()
|
||||
std::vector<signaling_message> get_sign_msgs()
|
||||
{
|
||||
std::vector<std::pair<std::pair<u32, u16>, std::vector<u8>>> msgs;
|
||||
std::vector<signaling_message> msgs;
|
||||
auto& nc = g_fxo->get<network_context>();
|
||||
{
|
||||
std::lock_guard list_lock(nc.list_p2p_ports_mutex);
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "sys_net_helpers.h"
|
||||
#include "Emu/NP/signaling_handler.h"
|
||||
#include "sys_net_helpers.h"
|
||||
#include "Emu/NP/vport0.h"
|
||||
|
||||
LOG_CHANNEL(sys_net);
|
||||
|
||||
@ -119,35 +120,48 @@ bool nt_p2p_port::recv_data()
|
||||
|
||||
u16 dst_vport = reinterpret_cast<le_t<u16>&>(p2p_recv_data[0]);
|
||||
|
||||
if (dst_vport == 0) // Reserved for messages from RPCN server
|
||||
if (dst_vport == 0)
|
||||
{
|
||||
std::vector<u8> rpcn_msg(recv_res - sizeof(u16));
|
||||
memcpy(rpcn_msg.data(), p2p_recv_data.data() + sizeof(u16), recv_res - sizeof(u16));
|
||||
|
||||
std::lock_guard lock(s_rpcn_mutex);
|
||||
rpcn_msgs.push_back(std::move(rpcn_msg));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (dst_vport == 65535) // Reserved for signaling
|
||||
{
|
||||
std::vector<u8> sign_msg(recv_res - sizeof(u16));
|
||||
memcpy(sign_msg.data(), p2p_recv_data.data() + sizeof(u16), recv_res - sizeof(u16));
|
||||
|
||||
std::pair<std::pair<u32, u16>, std::vector<u8>> msg;
|
||||
msg.first.first = reinterpret_cast<struct sockaddr_in*>(&native_addr)->sin_addr.s_addr;
|
||||
msg.first.second = std::bit_cast<u16, be_t<u16>>(reinterpret_cast<struct sockaddr_in*>(&native_addr)->sin_port);
|
||||
msg.second = std::move(sign_msg);
|
||||
|
||||
if (recv_res < VPORT_0_HEADER_SIZE)
|
||||
{
|
||||
std::lock_guard lock(s_sign_mutex);
|
||||
sign_msgs.push_back(std::move(msg));
|
||||
sys_net.error("Bad vport 0 packet(no subset)!");
|
||||
return true;
|
||||
}
|
||||
|
||||
auto& sigh = g_fxo->get<named_thread<signaling_handler>>();
|
||||
sigh.wake_up();
|
||||
const u8 subset = p2p_recv_data[2];
|
||||
const auto data_size = recv_res - VPORT_0_HEADER_SIZE;
|
||||
std::vector<u8> vport_0_data(p2p_recv_data.data() + VPORT_0_HEADER_SIZE, p2p_recv_data.data() + VPORT_0_HEADER_SIZE + data_size);
|
||||
|
||||
return true;
|
||||
switch (subset)
|
||||
{
|
||||
case SUBSET_RPCN:
|
||||
{
|
||||
std::lock_guard lock(s_rpcn_mutex);
|
||||
rpcn_msgs.push_back(std::move(vport_0_data));
|
||||
return true;
|
||||
}
|
||||
case SUBSET_SIGNALING:
|
||||
{
|
||||
signaling_message msg;
|
||||
msg.src_addr = reinterpret_cast<struct sockaddr_in*>(&native_addr)->sin_addr.s_addr;
|
||||
msg.src_port = std::bit_cast<u16, be_t<u16>>(reinterpret_cast<struct sockaddr_in*>(&native_addr)->sin_port);
|
||||
msg.data = std::move(vport_0_data);
|
||||
|
||||
{
|
||||
std::lock_guard lock(s_sign_mutex);
|
||||
sign_msgs.push_back(std::move(msg));
|
||||
}
|
||||
|
||||
auto& sigh = g_fxo->get<named_thread<signaling_handler>>();
|
||||
sigh.wake_up();
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
{
|
||||
sys_net.error("Invalid vport 0 subset!");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -18,6 +18,14 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
struct signaling_message
|
||||
{
|
||||
u32 src_addr = 0;
|
||||
u16 src_port = 0;
|
||||
|
||||
std::vector<u8> data;
|
||||
};
|
||||
|
||||
struct nt_p2p_port
|
||||
{
|
||||
// Real socket where P2P packets are received/sent
|
||||
@ -36,7 +44,7 @@ struct nt_p2p_port
|
||||
std::vector<std::vector<u8>> rpcn_msgs{};
|
||||
// Queued signaling messages
|
||||
shared_mutex s_sign_mutex;
|
||||
std::vector<std::pair<std::pair<u32, u16>, std::vector<u8>>> sign_msgs{};
|
||||
std::vector<signaling_message> sign_msgs{};
|
||||
|
||||
std::array<u8, 65535> p2p_recv_data{};
|
||||
|
||||
|
@ -154,7 +154,7 @@ namespace np
|
||||
SceNpMatching2RoomDataExternal* cur_room;
|
||||
|
||||
cur_room = (i > 0) ? edata.allocate<SceNpMatching2RoomDataExternal>(sizeof(SceNpMatching2RoomDataExternal), prev_room->next) :
|
||||
edata.allocate<SceNpMatching2RoomDataExternal>(sizeof(SceNpMatching2RoomDataExternal), search_resp->roomDataExternal);
|
||||
edata.allocate<SceNpMatching2RoomDataExternal>(sizeof(SceNpMatching2RoomDataExternal), search_resp->roomDataExternal);
|
||||
|
||||
RoomDataExternal_to_SceNpMatching2RoomDataExternal(edata, fb_room, cur_room);
|
||||
prev_room = cur_room;
|
||||
@ -173,7 +173,7 @@ namespace np
|
||||
SceNpMatching2RoomDataExternal* cur_room;
|
||||
|
||||
cur_room = (i > 0) ? edata.allocate<SceNpMatching2RoomDataExternal>(sizeof(SceNpMatching2RoomDataExternal), prev_room->next) :
|
||||
edata.allocate<SceNpMatching2RoomDataExternal>(sizeof(SceNpMatching2RoomDataExternal), get_resp->roomDataExternal);
|
||||
edata.allocate<SceNpMatching2RoomDataExternal>(sizeof(SceNpMatching2RoomDataExternal), get_resp->roomDataExternal);
|
||||
|
||||
RoomDataExternal_to_SceNpMatching2RoomDataExternal(edata, fb_room, cur_room);
|
||||
prev_room = cur_room;
|
||||
@ -370,10 +370,10 @@ namespace np
|
||||
{
|
||||
rpcn_log.todo("RoomDataInternalUpdateInfo::newRoomGroup");
|
||||
// TODO
|
||||
//sce_update_info->newRoomGroupNum = update_info->newRoomGroup()->size();
|
||||
//vm::ptr<SceNpMatching2RoomGroup> group_info(allocate(sizeof(SceNpMatching2RoomGroup) * sce_update_info->newRoomGroupNum));
|
||||
//RoomGroups_to_SceNpMatching2RoomGroup(update_info->newRoomGroup(), group_info);
|
||||
//sce_update_info->newRoomGroup = group_info;
|
||||
// sce_update_info->newRoomGroupNum = update_info->newRoomGroup()->size();
|
||||
// vm::ptr<SceNpMatching2RoomGroup> group_info(allocate(sizeof(SceNpMatching2RoomGroup) * sce_update_info->newRoomGroupNum));
|
||||
// RoomGroups_to_SceNpMatching2RoomGroup(update_info->newRoomGroup(), group_info);
|
||||
// sce_update_info->newRoomGroup = group_info;
|
||||
}
|
||||
|
||||
if (update_info->newRoomBinAttrInternal() && update_info->newRoomBinAttrInternal()->size() != 0)
|
||||
@ -497,5 +497,4 @@ namespace np
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace np
|
||||
|
@ -270,3 +270,69 @@ table SendMessageRequest {
|
||||
message:[uint8] (nested_flatbuffer: "MessageDetails");
|
||||
npids:[string];
|
||||
}
|
||||
|
||||
table BoardInfo {
|
||||
rankLimit:uint32;
|
||||
updateMode:uint32;
|
||||
sortMode:uint32;
|
||||
uploadNumLimit:uint32;
|
||||
uploadSizeLimit:uint32;
|
||||
}
|
||||
|
||||
table RecordScoreRequest {
|
||||
boardId:uint32;
|
||||
pcId:int32;
|
||||
score:int64;
|
||||
comment:string;
|
||||
data:[uint8];
|
||||
}
|
||||
|
||||
table GetScoreRangeRequest {
|
||||
boardId:uint32;
|
||||
startRank:uint32;
|
||||
numRanks:uint32;
|
||||
withComment:bool;
|
||||
withGameInfo:bool;
|
||||
}
|
||||
|
||||
table ScoreNpIdPcId {
|
||||
npid:string;
|
||||
pcId:int32;
|
||||
}
|
||||
|
||||
table GetScoreNpIdRequest {
|
||||
boardId:uint32;
|
||||
npids:[ScoreNpIdPcId];
|
||||
withComment:bool;
|
||||
withGameInfo:bool;
|
||||
}
|
||||
|
||||
table GetScoreFriendsRequest {
|
||||
boardId:uint32;
|
||||
include_self:bool;
|
||||
max:uint32;
|
||||
withComment:bool;
|
||||
withGameInfo:bool;
|
||||
}
|
||||
|
||||
table ScoreRankData {
|
||||
npId:string;
|
||||
onlineName:string;
|
||||
pcId:int32;
|
||||
rank:uint32;
|
||||
score:int64;
|
||||
hasGameData:bool;
|
||||
recordDate:uint64;
|
||||
}
|
||||
|
||||
table ScoreInfo {
|
||||
data: [uint8];
|
||||
}
|
||||
|
||||
table GetScoreResponse {
|
||||
rankArray:[ScoreRankData];
|
||||
commentArray:[string];
|
||||
infoArray:[ScoreInfo];
|
||||
lastSortDate:uint64;
|
||||
totalRecord:uint32;
|
||||
}
|
||||
|
@ -6,6 +6,13 @@
|
||||
|
||||
#include "flatbuffers/flatbuffers.h"
|
||||
|
||||
// Ensure the included flatbuffers.h is the same version as when this file was
|
||||
// generated, otherwise it may not be compatible.
|
||||
static_assert(FLATBUFFERS_VERSION_MAJOR == 2 &&
|
||||
FLATBUFFERS_VERSION_MINOR == 0 &&
|
||||
FLATBUFFERS_VERSION_REVISION == 8,
|
||||
"Non-compatible flatbuffers version included");
|
||||
|
||||
struct BinAttr;
|
||||
struct BinAttrBuilder;
|
||||
|
||||
@ -111,6 +118,33 @@ struct MessageDetailsBuilder;
|
||||
struct SendMessageRequest;
|
||||
struct SendMessageRequestBuilder;
|
||||
|
||||
struct BoardInfo;
|
||||
struct BoardInfoBuilder;
|
||||
|
||||
struct RecordScoreRequest;
|
||||
struct RecordScoreRequestBuilder;
|
||||
|
||||
struct GetScoreRangeRequest;
|
||||
struct GetScoreRangeRequestBuilder;
|
||||
|
||||
struct ScoreNpIdPcId;
|
||||
struct ScoreNpIdPcIdBuilder;
|
||||
|
||||
struct GetScoreNpIdRequest;
|
||||
struct GetScoreNpIdRequestBuilder;
|
||||
|
||||
struct GetScoreFriendsRequest;
|
||||
struct GetScoreFriendsRequestBuilder;
|
||||
|
||||
struct ScoreRankData;
|
||||
struct ScoreRankDataBuilder;
|
||||
|
||||
struct ScoreInfo;
|
||||
struct ScoreInfoBuilder;
|
||||
|
||||
struct GetScoreResponse;
|
||||
struct GetScoreResponseBuilder;
|
||||
|
||||
struct BinAttr FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
typedef BinAttrBuilder Builder;
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
@ -3460,4 +3494,781 @@ inline flatbuffers::Offset<SendMessageRequest> CreateSendMessageRequestDirect(
|
||||
npids__);
|
||||
}
|
||||
|
||||
struct BoardInfo FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
typedef BoardInfoBuilder Builder;
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
VT_RANKLIMIT = 4,
|
||||
VT_UPDATEMODE = 6,
|
||||
VT_SORTMODE = 8,
|
||||
VT_UPLOADNUMLIMIT = 10,
|
||||
VT_UPLOADSIZELIMIT = 12
|
||||
};
|
||||
uint32_t rankLimit() const {
|
||||
return GetField<uint32_t>(VT_RANKLIMIT, 0);
|
||||
}
|
||||
uint32_t updateMode() const {
|
||||
return GetField<uint32_t>(VT_UPDATEMODE, 0);
|
||||
}
|
||||
uint32_t sortMode() const {
|
||||
return GetField<uint32_t>(VT_SORTMODE, 0);
|
||||
}
|
||||
uint32_t uploadNumLimit() const {
|
||||
return GetField<uint32_t>(VT_UPLOADNUMLIMIT, 0);
|
||||
}
|
||||
uint32_t uploadSizeLimit() const {
|
||||
return GetField<uint32_t>(VT_UPLOADSIZELIMIT, 0);
|
||||
}
|
||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
VerifyField<uint32_t>(verifier, VT_RANKLIMIT, 4) &&
|
||||
VerifyField<uint32_t>(verifier, VT_UPDATEMODE, 4) &&
|
||||
VerifyField<uint32_t>(verifier, VT_SORTMODE, 4) &&
|
||||
VerifyField<uint32_t>(verifier, VT_UPLOADNUMLIMIT, 4) &&
|
||||
VerifyField<uint32_t>(verifier, VT_UPLOADSIZELIMIT, 4) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
};
|
||||
|
||||
struct BoardInfoBuilder {
|
||||
typedef BoardInfo Table;
|
||||
flatbuffers::FlatBufferBuilder &fbb_;
|
||||
flatbuffers::uoffset_t start_;
|
||||
void add_rankLimit(uint32_t rankLimit) {
|
||||
fbb_.AddElement<uint32_t>(BoardInfo::VT_RANKLIMIT, rankLimit, 0);
|
||||
}
|
||||
void add_updateMode(uint32_t updateMode) {
|
||||
fbb_.AddElement<uint32_t>(BoardInfo::VT_UPDATEMODE, updateMode, 0);
|
||||
}
|
||||
void add_sortMode(uint32_t sortMode) {
|
||||
fbb_.AddElement<uint32_t>(BoardInfo::VT_SORTMODE, sortMode, 0);
|
||||
}
|
||||
void add_uploadNumLimit(uint32_t uploadNumLimit) {
|
||||
fbb_.AddElement<uint32_t>(BoardInfo::VT_UPLOADNUMLIMIT, uploadNumLimit, 0);
|
||||
}
|
||||
void add_uploadSizeLimit(uint32_t uploadSizeLimit) {
|
||||
fbb_.AddElement<uint32_t>(BoardInfo::VT_UPLOADSIZELIMIT, uploadSizeLimit, 0);
|
||||
}
|
||||
explicit BoardInfoBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
||||
: fbb_(_fbb) {
|
||||
start_ = fbb_.StartTable();
|
||||
}
|
||||
flatbuffers::Offset<BoardInfo> Finish() {
|
||||
const auto end = fbb_.EndTable(start_);
|
||||
auto o = flatbuffers::Offset<BoardInfo>(end);
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
inline flatbuffers::Offset<BoardInfo> CreateBoardInfo(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
uint32_t rankLimit = 0,
|
||||
uint32_t updateMode = 0,
|
||||
uint32_t sortMode = 0,
|
||||
uint32_t uploadNumLimit = 0,
|
||||
uint32_t uploadSizeLimit = 0) {
|
||||
BoardInfoBuilder builder_(_fbb);
|
||||
builder_.add_uploadSizeLimit(uploadSizeLimit);
|
||||
builder_.add_uploadNumLimit(uploadNumLimit);
|
||||
builder_.add_sortMode(sortMode);
|
||||
builder_.add_updateMode(updateMode);
|
||||
builder_.add_rankLimit(rankLimit);
|
||||
return builder_.Finish();
|
||||
}
|
||||
|
||||
struct RecordScoreRequest FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
typedef RecordScoreRequestBuilder Builder;
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
VT_BOARDID = 4,
|
||||
VT_PCID = 6,
|
||||
VT_SCORE = 8,
|
||||
VT_COMMENT = 10,
|
||||
VT_DATA = 12
|
||||
};
|
||||
uint32_t boardId() const {
|
||||
return GetField<uint32_t>(VT_BOARDID, 0);
|
||||
}
|
||||
int32_t pcId() const {
|
||||
return GetField<int32_t>(VT_PCID, 0);
|
||||
}
|
||||
int64_t score() const {
|
||||
return GetField<int64_t>(VT_SCORE, 0);
|
||||
}
|
||||
const flatbuffers::String *comment() const {
|
||||
return GetPointer<const flatbuffers::String *>(VT_COMMENT);
|
||||
}
|
||||
const flatbuffers::Vector<uint8_t> *data() const {
|
||||
return GetPointer<const flatbuffers::Vector<uint8_t> *>(VT_DATA);
|
||||
}
|
||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
VerifyField<uint32_t>(verifier, VT_BOARDID, 4) &&
|
||||
VerifyField<int32_t>(verifier, VT_PCID, 4) &&
|
||||
VerifyField<int64_t>(verifier, VT_SCORE, 8) &&
|
||||
VerifyOffset(verifier, VT_COMMENT) &&
|
||||
verifier.VerifyString(comment()) &&
|
||||
VerifyOffset(verifier, VT_DATA) &&
|
||||
verifier.VerifyVector(data()) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
};
|
||||
|
||||
struct RecordScoreRequestBuilder {
|
||||
typedef RecordScoreRequest Table;
|
||||
flatbuffers::FlatBufferBuilder &fbb_;
|
||||
flatbuffers::uoffset_t start_;
|
||||
void add_boardId(uint32_t boardId) {
|
||||
fbb_.AddElement<uint32_t>(RecordScoreRequest::VT_BOARDID, boardId, 0);
|
||||
}
|
||||
void add_pcId(int32_t pcId) {
|
||||
fbb_.AddElement<int32_t>(RecordScoreRequest::VT_PCID, pcId, 0);
|
||||
}
|
||||
void add_score(int64_t score) {
|
||||
fbb_.AddElement<int64_t>(RecordScoreRequest::VT_SCORE, score, 0);
|
||||
}
|
||||
void add_comment(flatbuffers::Offset<flatbuffers::String> comment) {
|
||||
fbb_.AddOffset(RecordScoreRequest::VT_COMMENT, comment);
|
||||
}
|
||||
void add_data(flatbuffers::Offset<flatbuffers::Vector<uint8_t>> data) {
|
||||
fbb_.AddOffset(RecordScoreRequest::VT_DATA, data);
|
||||
}
|
||||
explicit RecordScoreRequestBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
||||
: fbb_(_fbb) {
|
||||
start_ = fbb_.StartTable();
|
||||
}
|
||||
flatbuffers::Offset<RecordScoreRequest> Finish() {
|
||||
const auto end = fbb_.EndTable(start_);
|
||||
auto o = flatbuffers::Offset<RecordScoreRequest>(end);
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
inline flatbuffers::Offset<RecordScoreRequest> CreateRecordScoreRequest(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
uint32_t boardId = 0,
|
||||
int32_t pcId = 0,
|
||||
int64_t score = 0,
|
||||
flatbuffers::Offset<flatbuffers::String> comment = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<uint8_t>> data = 0) {
|
||||
RecordScoreRequestBuilder builder_(_fbb);
|
||||
builder_.add_score(score);
|
||||
builder_.add_data(data);
|
||||
builder_.add_comment(comment);
|
||||
builder_.add_pcId(pcId);
|
||||
builder_.add_boardId(boardId);
|
||||
return builder_.Finish();
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<RecordScoreRequest> CreateRecordScoreRequestDirect(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
uint32_t boardId = 0,
|
||||
int32_t pcId = 0,
|
||||
int64_t score = 0,
|
||||
const char *comment = nullptr,
|
||||
const std::vector<uint8_t> *data = nullptr) {
|
||||
auto comment__ = comment ? _fbb.CreateString(comment) : 0;
|
||||
auto data__ = data ? _fbb.CreateVector<uint8_t>(*data) : 0;
|
||||
return CreateRecordScoreRequest(
|
||||
_fbb,
|
||||
boardId,
|
||||
pcId,
|
||||
score,
|
||||
comment__,
|
||||
data__);
|
||||
}
|
||||
|
||||
struct GetScoreRangeRequest FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
typedef GetScoreRangeRequestBuilder Builder;
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
VT_BOARDID = 4,
|
||||
VT_STARTRANK = 6,
|
||||
VT_NUMRANKS = 8,
|
||||
VT_WITHCOMMENT = 10,
|
||||
VT_WITHGAMEINFO = 12
|
||||
};
|
||||
uint32_t boardId() const {
|
||||
return GetField<uint32_t>(VT_BOARDID, 0);
|
||||
}
|
||||
uint32_t startRank() const {
|
||||
return GetField<uint32_t>(VT_STARTRANK, 0);
|
||||
}
|
||||
uint32_t numRanks() const {
|
||||
return GetField<uint32_t>(VT_NUMRANKS, 0);
|
||||
}
|
||||
bool withComment() const {
|
||||
return GetField<uint8_t>(VT_WITHCOMMENT, 0) != 0;
|
||||
}
|
||||
bool withGameInfo() const {
|
||||
return GetField<uint8_t>(VT_WITHGAMEINFO, 0) != 0;
|
||||
}
|
||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
VerifyField<uint32_t>(verifier, VT_BOARDID, 4) &&
|
||||
VerifyField<uint32_t>(verifier, VT_STARTRANK, 4) &&
|
||||
VerifyField<uint32_t>(verifier, VT_NUMRANKS, 4) &&
|
||||
VerifyField<uint8_t>(verifier, VT_WITHCOMMENT, 1) &&
|
||||
VerifyField<uint8_t>(verifier, VT_WITHGAMEINFO, 1) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
};
|
||||
|
||||
struct GetScoreRangeRequestBuilder {
|
||||
typedef GetScoreRangeRequest Table;
|
||||
flatbuffers::FlatBufferBuilder &fbb_;
|
||||
flatbuffers::uoffset_t start_;
|
||||
void add_boardId(uint32_t boardId) {
|
||||
fbb_.AddElement<uint32_t>(GetScoreRangeRequest::VT_BOARDID, boardId, 0);
|
||||
}
|
||||
void add_startRank(uint32_t startRank) {
|
||||
fbb_.AddElement<uint32_t>(GetScoreRangeRequest::VT_STARTRANK, startRank, 0);
|
||||
}
|
||||
void add_numRanks(uint32_t numRanks) {
|
||||
fbb_.AddElement<uint32_t>(GetScoreRangeRequest::VT_NUMRANKS, numRanks, 0);
|
||||
}
|
||||
void add_withComment(bool withComment) {
|
||||
fbb_.AddElement<uint8_t>(GetScoreRangeRequest::VT_WITHCOMMENT, static_cast<uint8_t>(withComment), 0);
|
||||
}
|
||||
void add_withGameInfo(bool withGameInfo) {
|
||||
fbb_.AddElement<uint8_t>(GetScoreRangeRequest::VT_WITHGAMEINFO, static_cast<uint8_t>(withGameInfo), 0);
|
||||
}
|
||||
explicit GetScoreRangeRequestBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
||||
: fbb_(_fbb) {
|
||||
start_ = fbb_.StartTable();
|
||||
}
|
||||
flatbuffers::Offset<GetScoreRangeRequest> Finish() {
|
||||
const auto end = fbb_.EndTable(start_);
|
||||
auto o = flatbuffers::Offset<GetScoreRangeRequest>(end);
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
inline flatbuffers::Offset<GetScoreRangeRequest> CreateGetScoreRangeRequest(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
uint32_t boardId = 0,
|
||||
uint32_t startRank = 0,
|
||||
uint32_t numRanks = 0,
|
||||
bool withComment = false,
|
||||
bool withGameInfo = false) {
|
||||
GetScoreRangeRequestBuilder builder_(_fbb);
|
||||
builder_.add_numRanks(numRanks);
|
||||
builder_.add_startRank(startRank);
|
||||
builder_.add_boardId(boardId);
|
||||
builder_.add_withGameInfo(withGameInfo);
|
||||
builder_.add_withComment(withComment);
|
||||
return builder_.Finish();
|
||||
}
|
||||
|
||||
struct ScoreNpIdPcId FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
typedef ScoreNpIdPcIdBuilder Builder;
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
VT_NPID = 4,
|
||||
VT_PCID = 6
|
||||
};
|
||||
const flatbuffers::String *npid() const {
|
||||
return GetPointer<const flatbuffers::String *>(VT_NPID);
|
||||
}
|
||||
int32_t pcId() const {
|
||||
return GetField<int32_t>(VT_PCID, 0);
|
||||
}
|
||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
VerifyOffset(verifier, VT_NPID) &&
|
||||
verifier.VerifyString(npid()) &&
|
||||
VerifyField<int32_t>(verifier, VT_PCID, 4) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
};
|
||||
|
||||
struct ScoreNpIdPcIdBuilder {
|
||||
typedef ScoreNpIdPcId Table;
|
||||
flatbuffers::FlatBufferBuilder &fbb_;
|
||||
flatbuffers::uoffset_t start_;
|
||||
void add_npid(flatbuffers::Offset<flatbuffers::String> npid) {
|
||||
fbb_.AddOffset(ScoreNpIdPcId::VT_NPID, npid);
|
||||
}
|
||||
void add_pcId(int32_t pcId) {
|
||||
fbb_.AddElement<int32_t>(ScoreNpIdPcId::VT_PCID, pcId, 0);
|
||||
}
|
||||
explicit ScoreNpIdPcIdBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
||||
: fbb_(_fbb) {
|
||||
start_ = fbb_.StartTable();
|
||||
}
|
||||
flatbuffers::Offset<ScoreNpIdPcId> Finish() {
|
||||
const auto end = fbb_.EndTable(start_);
|
||||
auto o = flatbuffers::Offset<ScoreNpIdPcId>(end);
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
inline flatbuffers::Offset<ScoreNpIdPcId> CreateScoreNpIdPcId(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
flatbuffers::Offset<flatbuffers::String> npid = 0,
|
||||
int32_t pcId = 0) {
|
||||
ScoreNpIdPcIdBuilder builder_(_fbb);
|
||||
builder_.add_pcId(pcId);
|
||||
builder_.add_npid(npid);
|
||||
return builder_.Finish();
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<ScoreNpIdPcId> CreateScoreNpIdPcIdDirect(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
const char *npid = nullptr,
|
||||
int32_t pcId = 0) {
|
||||
auto npid__ = npid ? _fbb.CreateString(npid) : 0;
|
||||
return CreateScoreNpIdPcId(
|
||||
_fbb,
|
||||
npid__,
|
||||
pcId);
|
||||
}
|
||||
|
||||
struct GetScoreNpIdRequest FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
typedef GetScoreNpIdRequestBuilder Builder;
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
VT_BOARDID = 4,
|
||||
VT_NPIDS = 6,
|
||||
VT_WITHCOMMENT = 8,
|
||||
VT_WITHGAMEINFO = 10
|
||||
};
|
||||
uint32_t boardId() const {
|
||||
return GetField<uint32_t>(VT_BOARDID, 0);
|
||||
}
|
||||
const flatbuffers::Vector<flatbuffers::Offset<ScoreNpIdPcId>> *npids() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<ScoreNpIdPcId>> *>(VT_NPIDS);
|
||||
}
|
||||
bool withComment() const {
|
||||
return GetField<uint8_t>(VT_WITHCOMMENT, 0) != 0;
|
||||
}
|
||||
bool withGameInfo() const {
|
||||
return GetField<uint8_t>(VT_WITHGAMEINFO, 0) != 0;
|
||||
}
|
||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
VerifyField<uint32_t>(verifier, VT_BOARDID, 4) &&
|
||||
VerifyOffset(verifier, VT_NPIDS) &&
|
||||
verifier.VerifyVector(npids()) &&
|
||||
verifier.VerifyVectorOfTables(npids()) &&
|
||||
VerifyField<uint8_t>(verifier, VT_WITHCOMMENT, 1) &&
|
||||
VerifyField<uint8_t>(verifier, VT_WITHGAMEINFO, 1) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
};
|
||||
|
||||
struct GetScoreNpIdRequestBuilder {
|
||||
typedef GetScoreNpIdRequest Table;
|
||||
flatbuffers::FlatBufferBuilder &fbb_;
|
||||
flatbuffers::uoffset_t start_;
|
||||
void add_boardId(uint32_t boardId) {
|
||||
fbb_.AddElement<uint32_t>(GetScoreNpIdRequest::VT_BOARDID, boardId, 0);
|
||||
}
|
||||
void add_npids(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<ScoreNpIdPcId>>> npids) {
|
||||
fbb_.AddOffset(GetScoreNpIdRequest::VT_NPIDS, npids);
|
||||
}
|
||||
void add_withComment(bool withComment) {
|
||||
fbb_.AddElement<uint8_t>(GetScoreNpIdRequest::VT_WITHCOMMENT, static_cast<uint8_t>(withComment), 0);
|
||||
}
|
||||
void add_withGameInfo(bool withGameInfo) {
|
||||
fbb_.AddElement<uint8_t>(GetScoreNpIdRequest::VT_WITHGAMEINFO, static_cast<uint8_t>(withGameInfo), 0);
|
||||
}
|
||||
explicit GetScoreNpIdRequestBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
||||
: fbb_(_fbb) {
|
||||
start_ = fbb_.StartTable();
|
||||
}
|
||||
flatbuffers::Offset<GetScoreNpIdRequest> Finish() {
|
||||
const auto end = fbb_.EndTable(start_);
|
||||
auto o = flatbuffers::Offset<GetScoreNpIdRequest>(end);
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
inline flatbuffers::Offset<GetScoreNpIdRequest> CreateGetScoreNpIdRequest(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
uint32_t boardId = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<ScoreNpIdPcId>>> npids = 0,
|
||||
bool withComment = false,
|
||||
bool withGameInfo = false) {
|
||||
GetScoreNpIdRequestBuilder builder_(_fbb);
|
||||
builder_.add_npids(npids);
|
||||
builder_.add_boardId(boardId);
|
||||
builder_.add_withGameInfo(withGameInfo);
|
||||
builder_.add_withComment(withComment);
|
||||
return builder_.Finish();
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<GetScoreNpIdRequest> CreateGetScoreNpIdRequestDirect(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
uint32_t boardId = 0,
|
||||
const std::vector<flatbuffers::Offset<ScoreNpIdPcId>> *npids = nullptr,
|
||||
bool withComment = false,
|
||||
bool withGameInfo = false) {
|
||||
auto npids__ = npids ? _fbb.CreateVector<flatbuffers::Offset<ScoreNpIdPcId>>(*npids) : 0;
|
||||
return CreateGetScoreNpIdRequest(
|
||||
_fbb,
|
||||
boardId,
|
||||
npids__,
|
||||
withComment,
|
||||
withGameInfo);
|
||||
}
|
||||
|
||||
struct GetScoreFriendsRequest FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
typedef GetScoreFriendsRequestBuilder Builder;
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
VT_BOARDID = 4,
|
||||
VT_INCLUDE_SELF = 6,
|
||||
VT_MAX = 8,
|
||||
VT_WITHCOMMENT = 10,
|
||||
VT_WITHGAMEINFO = 12
|
||||
};
|
||||
uint32_t boardId() const {
|
||||
return GetField<uint32_t>(VT_BOARDID, 0);
|
||||
}
|
||||
bool include_self() const {
|
||||
return GetField<uint8_t>(VT_INCLUDE_SELF, 0) != 0;
|
||||
}
|
||||
uint32_t max() const {
|
||||
return GetField<uint32_t>(VT_MAX, 0);
|
||||
}
|
||||
bool withComment() const {
|
||||
return GetField<uint8_t>(VT_WITHCOMMENT, 0) != 0;
|
||||
}
|
||||
bool withGameInfo() const {
|
||||
return GetField<uint8_t>(VT_WITHGAMEINFO, 0) != 0;
|
||||
}
|
||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
VerifyField<uint32_t>(verifier, VT_BOARDID, 4) &&
|
||||
VerifyField<uint8_t>(verifier, VT_INCLUDE_SELF, 1) &&
|
||||
VerifyField<uint32_t>(verifier, VT_MAX, 4) &&
|
||||
VerifyField<uint8_t>(verifier, VT_WITHCOMMENT, 1) &&
|
||||
VerifyField<uint8_t>(verifier, VT_WITHGAMEINFO, 1) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
};
|
||||
|
||||
struct GetScoreFriendsRequestBuilder {
|
||||
typedef GetScoreFriendsRequest Table;
|
||||
flatbuffers::FlatBufferBuilder &fbb_;
|
||||
flatbuffers::uoffset_t start_;
|
||||
void add_boardId(uint32_t boardId) {
|
||||
fbb_.AddElement<uint32_t>(GetScoreFriendsRequest::VT_BOARDID, boardId, 0);
|
||||
}
|
||||
void add_include_self(bool include_self) {
|
||||
fbb_.AddElement<uint8_t>(GetScoreFriendsRequest::VT_INCLUDE_SELF, static_cast<uint8_t>(include_self), 0);
|
||||
}
|
||||
void add_max(uint32_t max) {
|
||||
fbb_.AddElement<uint32_t>(GetScoreFriendsRequest::VT_MAX, max, 0);
|
||||
}
|
||||
void add_withComment(bool withComment) {
|
||||
fbb_.AddElement<uint8_t>(GetScoreFriendsRequest::VT_WITHCOMMENT, static_cast<uint8_t>(withComment), 0);
|
||||
}
|
||||
void add_withGameInfo(bool withGameInfo) {
|
||||
fbb_.AddElement<uint8_t>(GetScoreFriendsRequest::VT_WITHGAMEINFO, static_cast<uint8_t>(withGameInfo), 0);
|
||||
}
|
||||
explicit GetScoreFriendsRequestBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
||||
: fbb_(_fbb) {
|
||||
start_ = fbb_.StartTable();
|
||||
}
|
||||
flatbuffers::Offset<GetScoreFriendsRequest> Finish() {
|
||||
const auto end = fbb_.EndTable(start_);
|
||||
auto o = flatbuffers::Offset<GetScoreFriendsRequest>(end);
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
inline flatbuffers::Offset<GetScoreFriendsRequest> CreateGetScoreFriendsRequest(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
uint32_t boardId = 0,
|
||||
bool include_self = false,
|
||||
uint32_t max = 0,
|
||||
bool withComment = false,
|
||||
bool withGameInfo = false) {
|
||||
GetScoreFriendsRequestBuilder builder_(_fbb);
|
||||
builder_.add_max(max);
|
||||
builder_.add_boardId(boardId);
|
||||
builder_.add_withGameInfo(withGameInfo);
|
||||
builder_.add_withComment(withComment);
|
||||
builder_.add_include_self(include_self);
|
||||
return builder_.Finish();
|
||||
}
|
||||
|
||||
struct ScoreRankData FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
typedef ScoreRankDataBuilder Builder;
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
VT_NPID = 4,
|
||||
VT_ONLINENAME = 6,
|
||||
VT_PCID = 8,
|
||||
VT_RANK = 10,
|
||||
VT_SCORE = 12,
|
||||
VT_HASGAMEDATA = 14,
|
||||
VT_RECORDDATE = 16
|
||||
};
|
||||
const flatbuffers::String *npId() const {
|
||||
return GetPointer<const flatbuffers::String *>(VT_NPID);
|
||||
}
|
||||
const flatbuffers::String *onlineName() const {
|
||||
return GetPointer<const flatbuffers::String *>(VT_ONLINENAME);
|
||||
}
|
||||
int32_t pcId() const {
|
||||
return GetField<int32_t>(VT_PCID, 0);
|
||||
}
|
||||
uint32_t rank() const {
|
||||
return GetField<uint32_t>(VT_RANK, 0);
|
||||
}
|
||||
int64_t score() const {
|
||||
return GetField<int64_t>(VT_SCORE, 0);
|
||||
}
|
||||
bool hasGameData() const {
|
||||
return GetField<uint8_t>(VT_HASGAMEDATA, 0) != 0;
|
||||
}
|
||||
uint64_t recordDate() const {
|
||||
return GetField<uint64_t>(VT_RECORDDATE, 0);
|
||||
}
|
||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
VerifyOffset(verifier, VT_NPID) &&
|
||||
verifier.VerifyString(npId()) &&
|
||||
VerifyOffset(verifier, VT_ONLINENAME) &&
|
||||
verifier.VerifyString(onlineName()) &&
|
||||
VerifyField<int32_t>(verifier, VT_PCID, 4) &&
|
||||
VerifyField<uint32_t>(verifier, VT_RANK, 4) &&
|
||||
VerifyField<int64_t>(verifier, VT_SCORE, 8) &&
|
||||
VerifyField<uint8_t>(verifier, VT_HASGAMEDATA, 1) &&
|
||||
VerifyField<uint64_t>(verifier, VT_RECORDDATE, 8) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
};
|
||||
|
||||
struct ScoreRankDataBuilder {
|
||||
typedef ScoreRankData Table;
|
||||
flatbuffers::FlatBufferBuilder &fbb_;
|
||||
flatbuffers::uoffset_t start_;
|
||||
void add_npId(flatbuffers::Offset<flatbuffers::String> npId) {
|
||||
fbb_.AddOffset(ScoreRankData::VT_NPID, npId);
|
||||
}
|
||||
void add_onlineName(flatbuffers::Offset<flatbuffers::String> onlineName) {
|
||||
fbb_.AddOffset(ScoreRankData::VT_ONLINENAME, onlineName);
|
||||
}
|
||||
void add_pcId(int32_t pcId) {
|
||||
fbb_.AddElement<int32_t>(ScoreRankData::VT_PCID, pcId, 0);
|
||||
}
|
||||
void add_rank(uint32_t rank) {
|
||||
fbb_.AddElement<uint32_t>(ScoreRankData::VT_RANK, rank, 0);
|
||||
}
|
||||
void add_score(int64_t score) {
|
||||
fbb_.AddElement<int64_t>(ScoreRankData::VT_SCORE, score, 0);
|
||||
}
|
||||
void add_hasGameData(bool hasGameData) {
|
||||
fbb_.AddElement<uint8_t>(ScoreRankData::VT_HASGAMEDATA, static_cast<uint8_t>(hasGameData), 0);
|
||||
}
|
||||
void add_recordDate(uint64_t recordDate) {
|
||||
fbb_.AddElement<uint64_t>(ScoreRankData::VT_RECORDDATE, recordDate, 0);
|
||||
}
|
||||
explicit ScoreRankDataBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
||||
: fbb_(_fbb) {
|
||||
start_ = fbb_.StartTable();
|
||||
}
|
||||
flatbuffers::Offset<ScoreRankData> Finish() {
|
||||
const auto end = fbb_.EndTable(start_);
|
||||
auto o = flatbuffers::Offset<ScoreRankData>(end);
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
inline flatbuffers::Offset<ScoreRankData> CreateScoreRankData(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
flatbuffers::Offset<flatbuffers::String> npId = 0,
|
||||
flatbuffers::Offset<flatbuffers::String> onlineName = 0,
|
||||
int32_t pcId = 0,
|
||||
uint32_t rank = 0,
|
||||
int64_t score = 0,
|
||||
bool hasGameData = false,
|
||||
uint64_t recordDate = 0) {
|
||||
ScoreRankDataBuilder builder_(_fbb);
|
||||
builder_.add_recordDate(recordDate);
|
||||
builder_.add_score(score);
|
||||
builder_.add_rank(rank);
|
||||
builder_.add_pcId(pcId);
|
||||
builder_.add_onlineName(onlineName);
|
||||
builder_.add_npId(npId);
|
||||
builder_.add_hasGameData(hasGameData);
|
||||
return builder_.Finish();
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<ScoreRankData> CreateScoreRankDataDirect(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
const char *npId = nullptr,
|
||||
const char *onlineName = nullptr,
|
||||
int32_t pcId = 0,
|
||||
uint32_t rank = 0,
|
||||
int64_t score = 0,
|
||||
bool hasGameData = false,
|
||||
uint64_t recordDate = 0) {
|
||||
auto npId__ = npId ? _fbb.CreateString(npId) : 0;
|
||||
auto onlineName__ = onlineName ? _fbb.CreateString(onlineName) : 0;
|
||||
return CreateScoreRankData(
|
||||
_fbb,
|
||||
npId__,
|
||||
onlineName__,
|
||||
pcId,
|
||||
rank,
|
||||
score,
|
||||
hasGameData,
|
||||
recordDate);
|
||||
}
|
||||
|
||||
struct ScoreInfo FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
typedef ScoreInfoBuilder Builder;
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
VT_DATA = 4
|
||||
};
|
||||
const flatbuffers::Vector<uint8_t> *data() const {
|
||||
return GetPointer<const flatbuffers::Vector<uint8_t> *>(VT_DATA);
|
||||
}
|
||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
VerifyOffset(verifier, VT_DATA) &&
|
||||
verifier.VerifyVector(data()) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
};
|
||||
|
||||
struct ScoreInfoBuilder {
|
||||
typedef ScoreInfo Table;
|
||||
flatbuffers::FlatBufferBuilder &fbb_;
|
||||
flatbuffers::uoffset_t start_;
|
||||
void add_data(flatbuffers::Offset<flatbuffers::Vector<uint8_t>> data) {
|
||||
fbb_.AddOffset(ScoreInfo::VT_DATA, data);
|
||||
}
|
||||
explicit ScoreInfoBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
||||
: fbb_(_fbb) {
|
||||
start_ = fbb_.StartTable();
|
||||
}
|
||||
flatbuffers::Offset<ScoreInfo> Finish() {
|
||||
const auto end = fbb_.EndTable(start_);
|
||||
auto o = flatbuffers::Offset<ScoreInfo>(end);
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
inline flatbuffers::Offset<ScoreInfo> CreateScoreInfo(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
flatbuffers::Offset<flatbuffers::Vector<uint8_t>> data = 0) {
|
||||
ScoreInfoBuilder builder_(_fbb);
|
||||
builder_.add_data(data);
|
||||
return builder_.Finish();
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<ScoreInfo> CreateScoreInfoDirect(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
const std::vector<uint8_t> *data = nullptr) {
|
||||
auto data__ = data ? _fbb.CreateVector<uint8_t>(*data) : 0;
|
||||
return CreateScoreInfo(
|
||||
_fbb,
|
||||
data__);
|
||||
}
|
||||
|
||||
struct GetScoreResponse FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
typedef GetScoreResponseBuilder Builder;
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
VT_RANKARRAY = 4,
|
||||
VT_COMMENTARRAY = 6,
|
||||
VT_INFOARRAY = 8,
|
||||
VT_LASTSORTDATE = 10,
|
||||
VT_TOTALRECORD = 12
|
||||
};
|
||||
const flatbuffers::Vector<flatbuffers::Offset<ScoreRankData>> *rankArray() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<ScoreRankData>> *>(VT_RANKARRAY);
|
||||
}
|
||||
const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *commentArray() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(VT_COMMENTARRAY);
|
||||
}
|
||||
const flatbuffers::Vector<flatbuffers::Offset<ScoreInfo>> *infoArray() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<ScoreInfo>> *>(VT_INFOARRAY);
|
||||
}
|
||||
uint64_t lastSortDate() const {
|
||||
return GetField<uint64_t>(VT_LASTSORTDATE, 0);
|
||||
}
|
||||
uint32_t totalRecord() const {
|
||||
return GetField<uint32_t>(VT_TOTALRECORD, 0);
|
||||
}
|
||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
VerifyOffset(verifier, VT_RANKARRAY) &&
|
||||
verifier.VerifyVector(rankArray()) &&
|
||||
verifier.VerifyVectorOfTables(rankArray()) &&
|
||||
VerifyOffset(verifier, VT_COMMENTARRAY) &&
|
||||
verifier.VerifyVector(commentArray()) &&
|
||||
verifier.VerifyVectorOfStrings(commentArray()) &&
|
||||
VerifyOffset(verifier, VT_INFOARRAY) &&
|
||||
verifier.VerifyVector(infoArray()) &&
|
||||
verifier.VerifyVectorOfTables(infoArray()) &&
|
||||
VerifyField<uint64_t>(verifier, VT_LASTSORTDATE, 8) &&
|
||||
VerifyField<uint32_t>(verifier, VT_TOTALRECORD, 4) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
};
|
||||
|
||||
struct GetScoreResponseBuilder {
|
||||
typedef GetScoreResponse Table;
|
||||
flatbuffers::FlatBufferBuilder &fbb_;
|
||||
flatbuffers::uoffset_t start_;
|
||||
void add_rankArray(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<ScoreRankData>>> rankArray) {
|
||||
fbb_.AddOffset(GetScoreResponse::VT_RANKARRAY, rankArray);
|
||||
}
|
||||
void add_commentArray(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> commentArray) {
|
||||
fbb_.AddOffset(GetScoreResponse::VT_COMMENTARRAY, commentArray);
|
||||
}
|
||||
void add_infoArray(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<ScoreInfo>>> infoArray) {
|
||||
fbb_.AddOffset(GetScoreResponse::VT_INFOARRAY, infoArray);
|
||||
}
|
||||
void add_lastSortDate(uint64_t lastSortDate) {
|
||||
fbb_.AddElement<uint64_t>(GetScoreResponse::VT_LASTSORTDATE, lastSortDate, 0);
|
||||
}
|
||||
void add_totalRecord(uint32_t totalRecord) {
|
||||
fbb_.AddElement<uint32_t>(GetScoreResponse::VT_TOTALRECORD, totalRecord, 0);
|
||||
}
|
||||
explicit GetScoreResponseBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
||||
: fbb_(_fbb) {
|
||||
start_ = fbb_.StartTable();
|
||||
}
|
||||
flatbuffers::Offset<GetScoreResponse> Finish() {
|
||||
const auto end = fbb_.EndTable(start_);
|
||||
auto o = flatbuffers::Offset<GetScoreResponse>(end);
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
inline flatbuffers::Offset<GetScoreResponse> CreateGetScoreResponse(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<ScoreRankData>>> rankArray = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> commentArray = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<ScoreInfo>>> infoArray = 0,
|
||||
uint64_t lastSortDate = 0,
|
||||
uint32_t totalRecord = 0) {
|
||||
GetScoreResponseBuilder builder_(_fbb);
|
||||
builder_.add_lastSortDate(lastSortDate);
|
||||
builder_.add_totalRecord(totalRecord);
|
||||
builder_.add_infoArray(infoArray);
|
||||
builder_.add_commentArray(commentArray);
|
||||
builder_.add_rankArray(rankArray);
|
||||
return builder_.Finish();
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<GetScoreResponse> CreateGetScoreResponseDirect(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
const std::vector<flatbuffers::Offset<ScoreRankData>> *rankArray = nullptr,
|
||||
const std::vector<flatbuffers::Offset<flatbuffers::String>> *commentArray = nullptr,
|
||||
const std::vector<flatbuffers::Offset<ScoreInfo>> *infoArray = nullptr,
|
||||
uint64_t lastSortDate = 0,
|
||||
uint32_t totalRecord = 0) {
|
||||
auto rankArray__ = rankArray ? _fbb.CreateVector<flatbuffers::Offset<ScoreRankData>>(*rankArray) : 0;
|
||||
auto commentArray__ = commentArray ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*commentArray) : 0;
|
||||
auto infoArray__ = infoArray ? _fbb.CreateVector<flatbuffers::Offset<ScoreInfo>>(*infoArray) : 0;
|
||||
return CreateGetScoreResponse(
|
||||
_fbb,
|
||||
rankArray__,
|
||||
commentArray__,
|
||||
infoArray__,
|
||||
lastSortDate,
|
||||
totalRecord);
|
||||
}
|
||||
|
||||
#endif // FLATBUFFERS_GENERATED_NP2STRUCTS_H_
|
||||
|
@ -278,7 +278,7 @@ namespace np
|
||||
if (num_binattrs)
|
||||
{
|
||||
ptr_member->roomMemberBinAttrInternal.set(mem.allocate(sizeof(SceNpMatching2RoomMemberBinAttrInternal) * num_binattrs));
|
||||
ptr_member->roomMemberBinAttrInternalNum = num_binattrs;
|
||||
ptr_member->roomMemberBinAttrInternalNum = num_binattrs;
|
||||
SceNpMatching2RoomMemberBinAttrInternal* bin_ptr = ptr_member->roomMemberBinAttrInternal.get_ptr();
|
||||
|
||||
u32 actual_cnt = 0;
|
||||
@ -288,8 +288,8 @@ namespace np
|
||||
{
|
||||
const auto& bin = ::at32(member.bins, 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.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++;
|
||||
@ -299,4 +299,15 @@ namespace np
|
||||
|
||||
return needed_data_size;
|
||||
}
|
||||
} // namespace np
|
||||
|
||||
SceNpId cache_manager::get_npid(u64 room_id, u16 member_id)
|
||||
{
|
||||
std::lock_guard lock(mutex);
|
||||
|
||||
ensure(rooms.contains(room_id), "cache_manager::get_npid: Room not cached!");
|
||||
ensure(::at32(rooms, room_id).members.contains(member_id), "cache_manager::get_npid: Member not cached!");
|
||||
|
||||
return ::at32(::at32(rooms, room_id).members, member_id).userInfo.npId;
|
||||
}
|
||||
|
||||
} // namespace np
|
||||
|
@ -75,6 +75,7 @@ namespace np
|
||||
std::pair<error_code, std::vector<SceNpMatching2RoomMemberId>> get_memberids(u64 room_id, s32 sort_method);
|
||||
std::pair<error_code, std::optional<SceNpMatching2SessionPassword>> get_password(SceNpMatching2RoomId room_id);
|
||||
error_code get_member_and_attrs(SceNpMatching2RoomId room_id, SceNpMatching2RoomMemberId member_id, const std::vector<SceNpMatching2AttributeId>& binattrs_list, SceNpMatching2RoomMemberDataInternal* ptr_member, u32 addr_data, u32 size_data);
|
||||
SceNpId get_npid(u64 room_id, u16 member_id);
|
||||
|
||||
private:
|
||||
shared_mutex mutex;
|
||||
|
@ -3,6 +3,8 @@
|
||||
|
||||
#include "Emu/IdManager.h"
|
||||
|
||||
LOG_CHANNEL(sceNp2);
|
||||
|
||||
score_ctx::score_ctx(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpCommunicationPassphrase> passphrase)
|
||||
{
|
||||
ensure(!communicationId->data[9] && strlen(communicationId->data) == 9);
|
||||
@ -11,25 +13,72 @@ score_ctx::score_ctx(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<Sc
|
||||
}
|
||||
s32 create_score_context(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpCommunicationPassphrase> passphrase)
|
||||
{
|
||||
return static_cast<s32>(idm::make<score_ctx>(communicationId, passphrase));
|
||||
s32 score_id = idm::make<score_ctx>(communicationId, passphrase);
|
||||
|
||||
if (score_id == id_manager::id_traits<score_ctx>::invalid)
|
||||
{
|
||||
return SCE_NP_COMMUNITY_ERROR_TOO_MANY_OBJECTS;
|
||||
}
|
||||
|
||||
return static_cast<s32>(score_id);
|
||||
}
|
||||
bool destroy_score_context(s32 ctx_id)
|
||||
{
|
||||
return idm::remove<score_ctx>(static_cast<u32>(ctx_id));
|
||||
}
|
||||
|
||||
score_transaction_ctx::score_transaction_ctx(s32 score_context_id)
|
||||
score_transaction_ctx::score_transaction_ctx(const std::shared_ptr<score_ctx>& score)
|
||||
{
|
||||
this->score_context_id = score_context_id;
|
||||
pcId = score->pcId;
|
||||
communicationId = score->communicationId;
|
||||
passphrase = score->passphrase;
|
||||
timeout = score->timeout;
|
||||
}
|
||||
s32 create_score_transaction_context(s32 score_context_id)
|
||||
score_transaction_ctx::~score_transaction_ctx()
|
||||
{
|
||||
return static_cast<s32>(idm::make<score_transaction_ctx>(score_context_id));
|
||||
if (thread.joinable())
|
||||
thread.join();
|
||||
}
|
||||
|
||||
s32 create_score_transaction_context(const std::shared_ptr<score_ctx>& score)
|
||||
{
|
||||
s32 trans_id = idm::make<score_transaction_ctx>(score);
|
||||
|
||||
if (trans_id == id_manager::id_traits<score_transaction_ctx>::invalid)
|
||||
{
|
||||
return SCE_NP_COMMUNITY_ERROR_TOO_MANY_OBJECTS;
|
||||
}
|
||||
|
||||
return static_cast<s32>(trans_id);
|
||||
}
|
||||
bool destroy_score_transaction_context(s32 ctx_id)
|
||||
{
|
||||
return idm::remove<score_transaction_ctx>(static_cast<u32>(ctx_id));
|
||||
}
|
||||
std::optional<s32> score_transaction_ctx::get_score_transaction_status()
|
||||
{
|
||||
std::lock_guard lock(mutex);
|
||||
|
||||
return result;
|
||||
}
|
||||
void score_transaction_ctx::abort_score_transaction()
|
||||
{
|
||||
std::lock_guard lock(mutex);
|
||||
|
||||
result = SCE_NP_COMMUNITY_ERROR_ABORTED;
|
||||
wake_cond.notify_one();
|
||||
}
|
||||
void score_transaction_ctx::wait_for_completion()
|
||||
{
|
||||
std::unique_lock lock(mutex);
|
||||
|
||||
if (result)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
completion_cond.wait(lock);
|
||||
}
|
||||
|
||||
match2_ctx::match2_ctx(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpCommunicationPassphrase> passphrase)
|
||||
{
|
||||
@ -39,6 +88,7 @@ match2_ctx::match2_ctx(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<
|
||||
}
|
||||
u16 create_match2_context(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpCommunicationPassphrase> passphrase)
|
||||
{
|
||||
sceNp2.notice("Creating match2 context with communicationId: <%s>", static_cast<const char *>(communicationId->data));
|
||||
return static_cast<u16>(idm::make<match2_ctx>(communicationId, passphrase));
|
||||
}
|
||||
bool destroy_match2_context(u16 ctx_id)
|
||||
|
@ -1,5 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
#include <condition_variable>
|
||||
#include <thread>
|
||||
|
||||
#include "Utilities/mutex.h"
|
||||
|
||||
#include "Emu/Memory/vm_ptr.h"
|
||||
#include "Emu/Cell/Modules/sceNp.h"
|
||||
#include "Emu/Cell/Modules/sceNp2.h"
|
||||
@ -10,29 +16,51 @@ struct score_ctx
|
||||
{
|
||||
score_ctx(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpCommunicationPassphrase> passphrase);
|
||||
|
||||
static const u32 id_base = 1;
|
||||
static const u32 id_base = 0x2001;
|
||||
static const u32 id_step = 1;
|
||||
static const u32 id_count = 32;
|
||||
SAVESTATE_INIT_POS(25);
|
||||
|
||||
shared_mutex mutex;
|
||||
|
||||
u64 timeout = 60'000'000; // 60 seconds
|
||||
|
||||
SceNpCommunicationId communicationId{};
|
||||
SceNpCommunicationPassphrase passphrase{};
|
||||
s32 pcId = 0;
|
||||
};
|
||||
s32 create_score_context(vm::cptr<SceNpCommunicationId> communicationId, vm::cptr<SceNpCommunicationPassphrase> passphrase);
|
||||
bool destroy_score_context(s32 ctx_id);
|
||||
|
||||
struct score_transaction_ctx
|
||||
{
|
||||
score_transaction_ctx(s32 score_context_id);
|
||||
score_transaction_ctx(const std::shared_ptr<score_ctx>& score);
|
||||
~score_transaction_ctx();
|
||||
std::optional<s32> get_score_transaction_status();
|
||||
void abort_score_transaction();
|
||||
void wait_for_completion();
|
||||
|
||||
static const u32 id_base = 1;
|
||||
static const u32 id_base = 0x1001;
|
||||
static const u32 id_step = 1;
|
||||
static const u32 id_count = 32;
|
||||
SAVESTATE_INIT_POS(26);
|
||||
|
||||
s32 score_context_id = 0;
|
||||
shared_mutex mutex;
|
||||
std::condition_variable_any wake_cond, completion_cond;
|
||||
|
||||
std::optional<error_code> result;
|
||||
std::vector<u32> data;
|
||||
std::vector<u8> game_data;
|
||||
|
||||
u64 timeout = 60'000'000; // 60 seconds;
|
||||
|
||||
SceNpCommunicationId communicationId{};
|
||||
SceNpCommunicationPassphrase passphrase{};
|
||||
s32 pcId = 0;
|
||||
|
||||
std::thread thread;
|
||||
};
|
||||
s32 create_score_transaction_context(s32 score_context_id);
|
||||
s32 create_score_transaction_context(const std::shared_ptr<score_ctx>& score);
|
||||
bool destroy_score_transaction_context(s32 ctx_id);
|
||||
|
||||
// Match2 related
|
||||
@ -62,7 +90,7 @@ struct lookup_title_ctx
|
||||
{
|
||||
lookup_title_ctx(vm::cptr<SceNpCommunicationId> communicationId);
|
||||
|
||||
static const u32 id_base = 1;
|
||||
static const u32 id_base = 0x3001;
|
||||
static const u32 id_step = 1;
|
||||
static const u32 id_count = 32;
|
||||
SAVESTATE_INIT_POS(28);
|
||||
@ -77,7 +105,7 @@ struct lookup_transaction_ctx
|
||||
{
|
||||
lookup_transaction_ctx(s32 lt_ctx);
|
||||
|
||||
static const u32 id_base = 1;
|
||||
static const u32 id_base = 0x4001;
|
||||
static const u32 id_step = 1;
|
||||
static const u32 id_count = 32;
|
||||
SAVESTATE_INIT_POS(29);
|
||||
@ -91,7 +119,7 @@ struct commerce2_ctx
|
||||
{
|
||||
commerce2_ctx(u32 version, vm::cptr<SceNpId> npid, vm::ptr<SceNpCommerce2Handler> handler, vm::ptr<void> arg);
|
||||
|
||||
static const u32 id_base = 1;
|
||||
static const u32 id_base = 0x5001;
|
||||
static const u32 id_step = 1;
|
||||
static const u32 id_count = 32;
|
||||
SAVESTATE_INIT_POS(30);
|
||||
@ -109,7 +137,7 @@ struct signaling_ctx
|
||||
{
|
||||
signaling_ctx(vm::ptr<SceNpId> npid, vm::ptr<SceNpSignalingHandler> handler, vm::ptr<void> arg);
|
||||
|
||||
static const u32 id_base = 1;
|
||||
static const u32 id_base = 0x6001;
|
||||
static const u32 id_step = 1;
|
||||
static const u32 id_count = 32;
|
||||
SAVESTATE_INIT_POS(31);
|
||||
|
@ -384,9 +384,7 @@ namespace np
|
||||
return;
|
||||
}
|
||||
|
||||
ar(is_NP_Lookup_init, is_NP_Score_init, is_NP2_init, is_NP2_Match2_init, is_NP_Auth_init
|
||||
, manager_cb, manager_cb_arg, std::as_bytes(std::span(&basic_handler, 1)), is_connected, is_psn_active
|
||||
, hostname, ether_address, local_ip_addr, public_ip_addr, dns_ip);
|
||||
ar(is_NP_Lookup_init, is_NP_Score_init, is_NP2_init, is_NP2_Match2_init, is_NP_Auth_init, manager_cb, manager_cb_arg, std::as_bytes(std::span(&basic_handler, 1)), is_connected, is_psn_active, hostname, ether_address, local_ip_addr, public_ip_addr, dns_ip);
|
||||
|
||||
// Call init func if needed (np_memory is unaffected when an empty pool is provided)
|
||||
init_NP(0, vm::null);
|
||||
@ -396,6 +394,27 @@ namespace np
|
||||
// TODO: IDM-tied objects are not yet saved
|
||||
}
|
||||
|
||||
np_handler::~np_handler()
|
||||
{
|
||||
std::unordered_map<u32, std::shared_ptr<score_transaction_ctx>> moved_trans;
|
||||
{
|
||||
std::lock_guard lock(mutex_score_transactions);
|
||||
moved_trans = std::move(score_transactions);
|
||||
score_transactions.clear();
|
||||
}
|
||||
|
||||
for (auto& [trans_id, trans] : moved_trans)
|
||||
{
|
||||
trans->abort_score_transaction();
|
||||
}
|
||||
|
||||
for (auto& [trans_id, trans] : moved_trans)
|
||||
{
|
||||
if (trans->thread.joinable())
|
||||
trans->thread.join();
|
||||
}
|
||||
}
|
||||
|
||||
void np_handler::save(utils::serial& ar)
|
||||
{
|
||||
// TODO: See ctor
|
||||
@ -408,9 +427,7 @@ namespace np
|
||||
|
||||
USING_SERIALIZATION_VERSION(sceNp);
|
||||
|
||||
ar(is_NP_Lookup_init, is_NP_Score_init, is_NP2_init, is_NP2_Match2_init, is_NP_Auth_init
|
||||
, manager_cb, manager_cb_arg, std::as_bytes(std::span(&basic_handler, 1)), is_connected, is_psn_active
|
||||
, hostname, ether_address, local_ip_addr, public_ip_addr, dns_ip);
|
||||
ar(is_NP_Lookup_init, is_NP_Score_init, is_NP2_init, is_NP2_Match2_init, is_NP_Auth_init, manager_cb, manager_cb_arg, std::as_bytes(std::span(&basic_handler, 1)), is_connected, is_psn_active, hostname, ether_address, local_ip_addr, public_ip_addr, dns_ip);
|
||||
|
||||
np_memory.save(ar);
|
||||
}
|
||||
@ -454,10 +471,9 @@ namespace np
|
||||
return;
|
||||
}
|
||||
|
||||
// First address is used for now, (TODO combobox with possible local addresses to use?)
|
||||
local_ip_addr = *reinterpret_cast<u32*>(host->h_addr_list[0]);
|
||||
|
||||
// Set public address to local discovered address for now, may be updated later;
|
||||
// Set public address to local discovered address for now, may be updated later from RPCN socket
|
||||
public_ip_addr = local_ip_addr;
|
||||
|
||||
nph_log.notice("discover_ip_address: IP was determined to be %s", ip_to_string(local_ip_addr));
|
||||
@ -662,6 +678,7 @@ namespace np
|
||||
string_to_online_name(rpcn->get_online_name(), &online_name);
|
||||
string_to_avatar_url(rpcn->get_avatar_url(), &avatar_url);
|
||||
public_ip_addr = rpcn->get_addr_sig();
|
||||
local_ip_addr = std::bit_cast<u32, be_t<u32>>(rpcn->get_addr_local());
|
||||
|
||||
break;
|
||||
}
|
||||
@ -799,6 +816,13 @@ namespace np
|
||||
case rpcn::CommandType::SendRoomMessage: reply_send_room_message(req_id, data); break;
|
||||
case rpcn::CommandType::RequestSignalingInfos: reply_req_sign_infos(req_id, data); break;
|
||||
case rpcn::CommandType::RequestTicket: reply_req_ticket(req_id, data); break;
|
||||
case rpcn::CommandType::GetBoardInfos: reply_get_board_infos(req_id, data); break;
|
||||
case rpcn::CommandType::RecordScore: reply_record_score(req_id, data); break;
|
||||
case rpcn::CommandType::StoreScoreData: reply_store_score_data(req_id, data); break;
|
||||
case rpcn::CommandType::GetScoreData: reply_get_score_data(req_id, data); break;
|
||||
case rpcn::CommandType::GetScoreRange: reply_get_score_range(req_id, data); break;
|
||||
case rpcn::CommandType::GetScoreFriends: reply_get_score_friends(req_id, data); break;
|
||||
case rpcn::CommandType::GetScoreNpid: reply_get_score_npid(req_id, data); break;
|
||||
default: rpcn_log.error("Unknown reply(%d) received!", command); break;
|
||||
}
|
||||
}
|
||||
@ -896,16 +920,8 @@ namespace np
|
||||
const u32 req_id = get_req_id(optParam ? optParam->appReqId : ctx->default_match2_optparam.appReqId);
|
||||
|
||||
ret.ctx_id = ctx_id;
|
||||
ret.cb_arg = optParam ? optParam->cbFuncArg : ctx->default_match2_optparam.cbFuncArg;
|
||||
|
||||
if (optParam && optParam->cbFunc)
|
||||
{
|
||||
ret.cb = optParam->cbFunc;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret.cb = ctx->default_match2_optparam.cbFunc;
|
||||
}
|
||||
ret.cb_arg = (optParam && optParam->cbFuncArg) ? optParam->cbFuncArg : ctx->default_match2_optparam.cbFuncArg;
|
||||
ret.cb = (optParam && optParam->cbFunc) ? optParam->cbFunc : ctx->default_match2_optparam.cbFunc;
|
||||
|
||||
nph_log.warning("Callback used is 0x%x", ret.cb);
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "Emu/NP/np_allocator.h"
|
||||
#include "Emu/NP/np_cache.h"
|
||||
#include "Emu/NP/np_event_data.h"
|
||||
#include "Emu/NP/np_contexts.h"
|
||||
|
||||
namespace np
|
||||
{
|
||||
@ -69,6 +70,7 @@ namespace np
|
||||
SAVESTATE_INIT_POS(5);
|
||||
|
||||
np_handler();
|
||||
~np_handler();
|
||||
np_handler(utils::serial& ar);
|
||||
void save(utils::serial& ar);
|
||||
|
||||
@ -92,13 +94,13 @@ namespace np
|
||||
void init_NP(u32 poolsize, vm::ptr<void> poolptr);
|
||||
void terminate_NP();
|
||||
|
||||
bool is_netctl_init = false;
|
||||
bool is_NP_init = false;
|
||||
bool is_NP_Lookup_init = false;
|
||||
bool is_NP_Score_init = false;
|
||||
bool is_NP2_init = false;
|
||||
bool is_NP2_Match2_init = false;
|
||||
bool is_NP_Auth_init = false;
|
||||
atomic_t<bool> is_netctl_init = false;
|
||||
atomic_t<bool> is_NP_init = false;
|
||||
atomic_t<bool> is_NP_Lookup_init = false;
|
||||
atomic_t<bool> is_NP_Score_init = false;
|
||||
atomic_t<bool> is_NP2_init = false;
|
||||
atomic_t<bool> is_NP2_Match2_init = false;
|
||||
atomic_t<bool> is_NP_Auth_init = false;
|
||||
|
||||
// NP Handlers/Callbacks
|
||||
// Seems to be global
|
||||
@ -151,6 +153,14 @@ namespace np
|
||||
|
||||
u32 get_match2_event(SceNpMatching2EventKey event_key, u32 dest_addr, u32 size);
|
||||
|
||||
// Score requests
|
||||
void score_async_handler(std::unique_lock<shared_mutex> lock, const std::shared_ptr<score_transaction_ctx>& trans_ctx, u32 req_id, bool async);
|
||||
void get_board_infos(std::shared_ptr<score_transaction_ctx>& trans_ctx, SceNpScoreBoardId board_id, vm::ptr<SceNpScoreBoardInfo> board_info, bool async);
|
||||
void record_score(std::shared_ptr<score_transaction_ctx>& trans_ctx, SceNpScoreBoardId board_id, SceNpScoreValue score, vm::cptr<SceNpScoreComment> comment, const u8* data, u32 data_size, vm::ptr<SceNpScoreRankNumber> tmp_rank, bool async);
|
||||
void get_score_range(std::shared_ptr<score_transaction_ctx>& trans_ctx, SceNpScoreBoardId boardId, SceNpScoreRankNumber startSerialRank, vm::ptr<SceNpScoreRankData> rankArray, u64 rankArraySize, vm::ptr<SceNpScoreComment> commentArray, u64 commentArraySize, vm::ptr<void> infoArray, u64 infoArraySize, u64 arrayNum, vm::ptr<CellRtcTick> lastSortDate, vm::ptr<SceNpScoreRankNumber> totalRecord, bool async);
|
||||
void get_score_npid(std::shared_ptr<score_transaction_ctx>& trans_ctx, SceNpScoreBoardId boardId, const std::vector<std::pair<SceNpId, s32>>& npid_vec, vm::ptr<SceNpScorePlayerRankData> rankArray, u64 rankArraySize, vm::ptr<SceNpScoreComment> commentArray, u64 commentArraySize, vm::ptr<void> infoArray, u64 infoArraySize, u64 arrayNum, vm::ptr<CellRtcTick> lastSortDate, vm::ptr<SceNpScoreRankNumber> totalRecord, bool async);
|
||||
void get_score_friend(std::shared_ptr<score_transaction_ctx>& trans_ctx, SceNpScoreBoardId boardId, vm::ptr<SceNpScoreRankData> rankArray, u64 rankArraySize, vm::ptr<SceNpScoreComment> commentArray, u64 commentArraySize, vm::ptr<void> infoArray, u64 infoArraySize, u64 arrayNum, vm::ptr<CellRtcTick> lastSortDate, vm::ptr<SceNpScoreRankNumber> totalRecord, bool async);
|
||||
|
||||
// Local functions
|
||||
std::pair<error_code, std::optional<SceNpMatching2RoomSlotInfo>> local_get_room_slots(SceNpMatching2RoomId room_id);
|
||||
std::pair<error_code, std::optional<SceNpMatching2SessionPassword>> local_get_room_password(SceNpMatching2RoomId room_id);
|
||||
@ -173,7 +183,7 @@ namespace np
|
||||
// For custom menu
|
||||
struct custom_menu_action
|
||||
{
|
||||
s32 id = 0;
|
||||
s32 id = 0;
|
||||
u32 mask = SCE_NP_CUSTOM_MENU_ACTION_MASK_ME;
|
||||
std::string name;
|
||||
};
|
||||
@ -220,6 +230,13 @@ namespace np
|
||||
bool reply_send_room_message(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_req_sign_infos(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_req_ticket(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_get_board_infos(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_record_score(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_store_score_data(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_get_score_data(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_get_score_range(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_get_score_friends(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_get_score_npid(u32 req_id, std::vector<u8>& reply_data);
|
||||
|
||||
// Helper functions(fb=>np2)
|
||||
void BinAttr_to_SceNpMatching2BinAttr(event_data& edata, const BinAttr* bin_attr, SceNpMatching2BinAttr* binattr_info);
|
||||
@ -240,6 +257,7 @@ namespace np
|
||||
void RoomMessageInfo_to_SceNpMatching2RoomMessageInfo(event_data& edata, const RoomMessageInfo* mi, SceNpMatching2RoomMessageInfo* sce_mi);
|
||||
void RoomDataInternalUpdateInfo_to_SceNpMatching2RoomDataInternalUpdateInfo(event_data& edata, const RoomDataInternalUpdateInfo* update_info, SceNpMatching2RoomDataInternalUpdateInfo* sce_update_info, const SceNpId& npid);
|
||||
void RoomMemberDataInternalUpdateInfo_to_SceNpMatching2RoomMemberDataInternalUpdateInfo(event_data& edata, const RoomMemberDataInternalUpdateInfo* update_info, SceNpMatching2RoomMemberDataInternalUpdateInfo* sce_update_info);
|
||||
bool handle_GetScoreResponse(u32 req_id, std::vector<u8>& reply_data);
|
||||
|
||||
struct callback_info
|
||||
{
|
||||
@ -298,6 +316,10 @@ namespace np
|
||||
}
|
||||
event_data& allocate_req_result(u32 event_key, u32 max_size, u32 initial_size);
|
||||
|
||||
// Async score threads
|
||||
shared_mutex mutex_score_transactions;
|
||||
std::unordered_map<u32, std::shared_ptr<score_transaction_ctx>> score_transactions; // (req_id, transaction_ctx)
|
||||
|
||||
// RPCN
|
||||
shared_mutex mutex_rpcn;
|
||||
std::shared_ptr<rpcn::rpcn_client> rpcn;
|
||||
|
@ -22,24 +22,24 @@ namespace np
|
||||
return fmt::format("%02X:%02X:%02X:%02X:%02X:%02X", ether[0], ether[1], ether[2], ether[3], ether[4], ether[5]);
|
||||
}
|
||||
|
||||
void string_to_npid(const std::string& str, SceNpId* npid)
|
||||
void string_to_npid(std::string_view str, SceNpId* npid)
|
||||
{
|
||||
memset(npid, 0, sizeof(SceNpId));
|
||||
strcpy_trunc(npid->handle.data, str);
|
||||
// npid->reserved[0] = 1;
|
||||
}
|
||||
|
||||
void string_to_online_name(const std::string& str, SceNpOnlineName* online_name)
|
||||
void string_to_online_name(std::string_view str, SceNpOnlineName* online_name)
|
||||
{
|
||||
strcpy_trunc(online_name->data, str);
|
||||
}
|
||||
|
||||
void string_to_avatar_url(const std::string& str, SceNpAvatarUrl* avatar_url)
|
||||
void string_to_avatar_url(std::string_view str, SceNpAvatarUrl* avatar_url)
|
||||
{
|
||||
strcpy_trunc(avatar_url->data, str);
|
||||
}
|
||||
|
||||
void string_to_communication_id(const std::string& str, SceNpCommunicationId* comm_id)
|
||||
void string_to_communication_id(std::string_view str, SceNpCommunicationId* comm_id)
|
||||
{
|
||||
strcpy_trunc(comm_id->data, str);
|
||||
}
|
||||
|
@ -7,8 +7,8 @@ namespace np
|
||||
std::string ip_to_string(u32 addr);
|
||||
std::string ether_to_string(std::array<u8, 6>& ether);
|
||||
|
||||
void string_to_npid(const std::string& str, SceNpId* npid);
|
||||
void string_to_online_name(const std::string& str, SceNpOnlineName* online_name);
|
||||
void string_to_avatar_url(const std::string& str, SceNpAvatarUrl* avatar_url);
|
||||
void string_to_communication_id(const std::string& str, SceNpCommunicationId* comm_id);
|
||||
void string_to_npid(std::string_view str, SceNpId* npid);
|
||||
void string_to_online_name(std::string_view str, SceNpOnlineName* online_name);
|
||||
void string_to_avatar_url(std::string_view str, SceNpAvatarUrl* avatar_url);
|
||||
void string_to_communication_id(std::string_view str, SceNpCommunicationId* comm_id);
|
||||
}
|
||||
|
@ -221,7 +221,7 @@ namespace np
|
||||
|
||||
// Attempt Signaling
|
||||
auto& sigh = g_fxo->get<named_thread<signaling_handler>>();
|
||||
sigh.set_sig2_infos(room_id, member_id, SCE_NP_SIGNALING_CONN_STATUS_PENDING, addr_p2p, port_p2p);
|
||||
sigh.set_sig2_infos(room_id, member_id, SCE_NP_SIGNALING_CONN_STATUS_PENDING, addr_p2p, port_p2p, np_cache.get_npid(room_id, member_id));
|
||||
sigh.start_sig2(room_id, member_id);
|
||||
}
|
||||
} // namespace np
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "Emu/IdManager.h"
|
||||
#include "np_handler.h"
|
||||
#include "np_contexts.h"
|
||||
#include "np_helpers.h"
|
||||
#include "np_structs_extra.h"
|
||||
|
||||
LOG_CHANNEL(rpcn_log, "rpcn");
|
||||
@ -163,6 +164,8 @@ namespace np
|
||||
{
|
||||
u32 req_id = generate_callback_info(ctx_id, optParam);
|
||||
|
||||
extra_nps::print_createjoinroom(req);
|
||||
|
||||
if (!rpcn->createjoin_room(req_id, get_match2_context(ctx_id)->communicationId, req))
|
||||
{
|
||||
rpcn_log.error("Disconnecting from RPCN!");
|
||||
@ -200,7 +203,7 @@ namespace np
|
||||
// Establish Matching2 self signaling info
|
||||
auto& sigh = g_fxo->get<named_thread<signaling_handler>>();
|
||||
sigh.set_self_sig2_info(room_info->roomId, 1);
|
||||
sigh.set_sig2_infos(room_info->roomId, 1, SCE_NP_SIGNALING_CONN_STATUS_ACTIVE, rpcn->get_addr_sig(), rpcn->get_port_sig(), true);
|
||||
sigh.set_sig2_infos(room_info->roomId, 1, SCE_NP_SIGNALING_CONN_STATUS_ACTIVE, rpcn->get_addr_sig(), rpcn->get_port_sig(), get_npid(), true);
|
||||
// TODO? Should this send a message to Signaling CB? Is this even necessary?
|
||||
|
||||
extra_nps::print_create_room_resp(room_resp);
|
||||
@ -221,6 +224,8 @@ namespace np
|
||||
{
|
||||
u32 req_id = generate_callback_info(ctx_id, optParam);
|
||||
|
||||
extra_nps::print_joinroom(req);
|
||||
|
||||
if (!rpcn->join_room(req_id, get_match2_context(ctx_id)->communicationId, req))
|
||||
{
|
||||
rpcn_log.error("Disconnecting from RPCN!");
|
||||
@ -257,7 +262,7 @@ namespace np
|
||||
// Establish Matching2 self signaling info
|
||||
auto& sigh = g_fxo->get<named_thread<signaling_handler>>();
|
||||
sigh.set_self_sig2_info(room_info->roomId, member_id);
|
||||
sigh.set_sig2_infos(room_info->roomId, member_id, SCE_NP_SIGNALING_CONN_STATUS_ACTIVE, rpcn->get_addr_sig(), rpcn->get_port_sig(), true);
|
||||
sigh.set_sig2_infos(room_info->roomId, member_id, SCE_NP_SIGNALING_CONN_STATUS_ACTIVE, rpcn->get_addr_sig(), rpcn->get_port_sig(), get_npid(), true);
|
||||
// TODO? Should this send a message to Signaling CB? Is this even necessary?
|
||||
|
||||
if (cb_info.cb)
|
||||
@ -316,6 +321,8 @@ namespace np
|
||||
{
|
||||
u32 req_id = generate_callback_info(ctx_id, optParam);
|
||||
|
||||
extra_nps::print_search_room(req);
|
||||
|
||||
if (!rpcn->search_room(req_id, get_match2_context(ctx_id)->communicationId, req))
|
||||
{
|
||||
rpcn_log.error("Disconnecting from RPCN!");
|
||||
@ -342,6 +349,8 @@ namespace np
|
||||
SearchRoomResponse_to_SceNpMatching2SearchRoomResponse(edata, resp, search_resp);
|
||||
np_memory.shrink_allocation(edata.addr(), edata.size());
|
||||
|
||||
extra_nps::print_search_room_resp(search_resp);
|
||||
|
||||
if (cb_info.cb)
|
||||
{
|
||||
sysutil_register_cb([=, size = edata.size()](ppu_thread& cb_ppu) -> s32
|
||||
@ -358,6 +367,8 @@ namespace np
|
||||
{
|
||||
u32 req_id = generate_callback_info(ctx_id, optParam);
|
||||
|
||||
extra_nps::print_get_roomdata_external_list_req(req);
|
||||
|
||||
if (!rpcn->get_roomdata_external_list(req_id, get_match2_context(ctx_id)->communicationId, req))
|
||||
{
|
||||
rpcn_log.error("Disconnecting from RPCN!");
|
||||
@ -384,6 +395,8 @@ namespace np
|
||||
GetRoomDataExternalListResponse_to_SceNpMatching2GetRoomDataExternalListResponse(edata, resp, sce_get_room_ext_resp);
|
||||
np_memory.shrink_allocation(edata.addr(), edata.size());
|
||||
|
||||
extra_nps::print_get_roomdata_external_list_resp(sce_get_room_ext_resp);
|
||||
|
||||
if (cb_info.cb)
|
||||
{
|
||||
sysutil_register_cb([=, size = edata.size()](ppu_thread& cb_ppu) -> s32
|
||||
@ -482,6 +495,8 @@ namespace np
|
||||
{
|
||||
u32 req_id = generate_callback_info(ctx_id, optParam);
|
||||
|
||||
// TODO: extra_nps::print_set_roomdata_req(req);
|
||||
|
||||
extra_nps::print_set_roomdata_int_req(req);
|
||||
|
||||
if (!rpcn->set_roomdata_internal(req_id, get_match2_context(ctx_id)->communicationId, req))
|
||||
@ -515,6 +530,8 @@ namespace np
|
||||
{
|
||||
u32 req_id = generate_callback_info(ctx_id, optParam);
|
||||
|
||||
extra_nps::print_set_roommemberdata_int_req(req);
|
||||
|
||||
if (!rpcn->set_roommemberdata_internal(req_id, get_match2_context(ctx_id)->communicationId, req))
|
||||
{
|
||||
rpcn_log.error("Disconnecting from RPCN!");
|
||||
@ -703,4 +720,342 @@ namespace np
|
||||
return true;
|
||||
}
|
||||
|
||||
void np_handler::score_async_handler(std::unique_lock<shared_mutex> lock, const std::shared_ptr<score_transaction_ctx>& trans_ctx, u32 req_id, bool async)
|
||||
{
|
||||
auto worker_function = [trans_ctx = trans_ctx, req_id, this](std::unique_lock<shared_mutex> lock)
|
||||
{
|
||||
auto res = trans_ctx->wake_cond.wait_for(lock, std::chrono::microseconds(trans_ctx->timeout));
|
||||
{
|
||||
std::lock_guard lock_threads(this->mutex_score_transactions);
|
||||
this->score_transactions.erase(req_id);
|
||||
}
|
||||
|
||||
if (res == std::cv_status::timeout)
|
||||
{
|
||||
trans_ctx->result = SCE_NP_COMMUNITY_ERROR_TIMEOUT;
|
||||
return;
|
||||
}
|
||||
|
||||
// Only 2 cases should be timeout or caller setting result
|
||||
ensure(trans_ctx->result);
|
||||
|
||||
trans_ctx->completion_cond.notify_one();
|
||||
};
|
||||
|
||||
{
|
||||
std::lock_guard lock_score(mutex_score_transactions);
|
||||
ensure(score_transactions.insert({req_id, trans_ctx}).second);
|
||||
}
|
||||
|
||||
if (async)
|
||||
{
|
||||
trans_ctx->thread = std::thread(worker_function, std::move(lock));
|
||||
return;
|
||||
}
|
||||
|
||||
return worker_function(std::move(lock));
|
||||
}
|
||||
|
||||
void np_handler::get_board_infos(std::shared_ptr<score_transaction_ctx>& trans_ctx, SceNpScoreBoardId board_id, vm::ptr<SceNpScoreBoardInfo> board_info, bool async)
|
||||
{
|
||||
std::unique_lock lock(trans_ctx->mutex);
|
||||
|
||||
u32 req_id = get_req_id(0x3334);
|
||||
std::string comm_id(static_cast<const char*>(trans_ctx->communicationId.data));
|
||||
|
||||
trans_ctx->data.clear();
|
||||
trans_ctx->data.push_back(board_info.addr());
|
||||
rpcn->get_board_infos(req_id, trans_ctx->communicationId, board_id);
|
||||
|
||||
return score_async_handler(std::move(lock), trans_ctx, req_id, async);
|
||||
}
|
||||
|
||||
bool np_handler::reply_get_board_infos(u32 req_id, std::vector<u8>& reply_data)
|
||||
{
|
||||
vec_stream reply(reply_data, 1);
|
||||
|
||||
auto raw_board_info = reply.get_rawdata();
|
||||
auto* resp = flatbuffers::GetRoot<BoardInfo>(raw_board_info.data());
|
||||
|
||||
SceNpScoreBoardInfo board_info;
|
||||
|
||||
board_info.rankLimit = resp->rankLimit();
|
||||
board_info.updateMode = resp->updateMode();
|
||||
board_info.sortMode = resp->sortMode();
|
||||
board_info.uploadNumLimit = resp->uploadNumLimit();
|
||||
board_info.uploadSizeLimit = resp->uploadSizeLimit();
|
||||
|
||||
std::lock_guard lock_trans(mutex_score_transactions);
|
||||
if (!score_transactions.count(req_id))
|
||||
{
|
||||
rpcn_log.error("Couldn't find transaction(%d) in trans_id!", req_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto trans = ::at32(score_transactions, req_id);
|
||||
std::lock_guard lock(trans->mutex);
|
||||
ensure(trans->data.size() == 1);
|
||||
vm::ptr<SceNpScoreBoardInfo> boardinfo_ptr = vm::cast(trans->data[0]);
|
||||
memcpy(reinterpret_cast<u8*>(boardinfo_ptr.get_ptr()), &board_info, sizeof(SceNpScoreBoardInfo));
|
||||
trans->result = CELL_OK;
|
||||
trans->wake_cond.notify_one();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void np_handler::record_score(std::shared_ptr<score_transaction_ctx>& trans_ctx, SceNpScoreBoardId board_id, SceNpScoreValue score, vm::cptr<SceNpScoreComment> comment, const u8* data, u32 data_size, vm::ptr<SceNpScoreRankNumber> tmp_rank, bool async)
|
||||
{
|
||||
std::unique_lock lock(trans_ctx->mutex);
|
||||
u32 req_id = get_req_id(0x3334);
|
||||
std::optional<std::string> str_comment = comment ? std::optional(std::string(reinterpret_cast<const char*>(comment->data))) : std::nullopt;
|
||||
std::optional<std::vector<u8>> vec_data = data ? std::optional(std::vector(data, data + data_size)) : std::nullopt;
|
||||
trans_ctx->data.clear();
|
||||
if (tmp_rank)
|
||||
{
|
||||
trans_ctx->data.push_back(tmp_rank.addr());
|
||||
}
|
||||
|
||||
rpcn->record_score(req_id, trans_ctx->communicationId, board_id, trans_ctx->pcId, score, str_comment, vec_data);
|
||||
|
||||
return score_async_handler(std::move(lock), trans_ctx, req_id, async);
|
||||
}
|
||||
|
||||
bool np_handler::reply_record_score(u32 req_id, std::vector<u8>& reply_data)
|
||||
{
|
||||
std::lock_guard lock_trans(mutex_score_transactions);
|
||||
if (!score_transactions.count(req_id))
|
||||
{
|
||||
rpcn_log.error("Couldn't find transaction(%d) in trans_id!", req_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto trans = ::at32(score_transactions, req_id);
|
||||
std::lock_guard lock(trans->mutex);
|
||||
|
||||
if (rpcn::is_error(static_cast<rpcn::ErrorType>(reply_data[0])))
|
||||
{
|
||||
switch (reply_data[0])
|
||||
{
|
||||
case rpcn::ErrorType::ScoreNotBest:
|
||||
{
|
||||
trans->result = SCE_NP_COMMUNITY_SERVER_ERROR_NOT_BEST_SCORE;
|
||||
trans->wake_cond.notify_one();
|
||||
return true;
|
||||
}
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
vec_stream reply(reply_data, 1);
|
||||
auto tmp_rank = reply.get<u32>();
|
||||
|
||||
if (reply.is_error())
|
||||
{
|
||||
rpcn_log.error("Error parsing response in reply_record_score");
|
||||
return false;
|
||||
}
|
||||
|
||||
ensure(trans->data.size() == 1 || trans->data.size() == 0);
|
||||
if (!trans->data.empty())
|
||||
{
|
||||
vm::ptr<u32> tmprank_ptr = vm::cast(trans->data[0]);
|
||||
*tmprank_ptr = tmp_rank;
|
||||
}
|
||||
|
||||
trans->result = CELL_OK;
|
||||
trans->wake_cond.notify_one();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool np_handler::reply_store_score_data(u32 req_id, std::vector<u8>& reply_data)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool np_handler::reply_get_score_data(u32 req_id, std::vector<u8>& reply_data)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void np_handler::get_score_range(std::shared_ptr<score_transaction_ctx>& trans_ctx, SceNpScoreBoardId boardId, SceNpScoreRankNumber startSerialRank, vm::ptr<SceNpScoreRankData> rankArray, [[maybe_unused]] u64 rankArraySize, vm::ptr<SceNpScoreComment> commentArray, [[maybe_unused]] u64 commentArraySize, vm::ptr<void> infoArray, u64 infoArraySize, u64 arrayNum, vm::ptr<CellRtcTick> lastSortDate, vm::ptr<SceNpScoreRankNumber> totalRecord, bool async)
|
||||
{
|
||||
std::unique_lock lock(trans_ctx->mutex);
|
||||
u32 req_id = get_req_id(0x3334);
|
||||
trans_ctx->data.clear();
|
||||
trans_ctx->data.push_back(static_cast<u32>(arrayNum));
|
||||
trans_ctx->data.push_back(rankArray.addr());
|
||||
trans_ctx->data.push_back(commentArray.addr());
|
||||
trans_ctx->data.push_back(infoArray.addr());
|
||||
trans_ctx->data.push_back(static_cast<u32>((arrayNum * sizeof(SceNpScoreGameInfo)) == infoArraySize));
|
||||
trans_ctx->data.push_back(lastSortDate.addr());
|
||||
trans_ctx->data.push_back(totalRecord.addr());
|
||||
|
||||
bool with_comments = !!commentArray;
|
||||
bool with_gameinfo = !!infoArray;
|
||||
|
||||
rpcn->get_score_range(req_id, trans_ctx->communicationId, boardId, startSerialRank, arrayNum, with_comments, with_gameinfo);
|
||||
|
||||
return score_async_handler(std::move(lock), trans_ctx, req_id, async);
|
||||
}
|
||||
|
||||
bool np_handler::handle_GetScoreResponse(u32 req_id, std::vector<u8>& reply_data)
|
||||
{
|
||||
std::lock_guard lock_trans(mutex_score_transactions);
|
||||
if (!score_transactions.count(req_id))
|
||||
{
|
||||
rpcn_log.error("Couldn't find transaction(%d) in trans_id!", req_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto trans_ctx = ::at32(score_transactions, req_id);
|
||||
std::lock_guard lock(trans_ctx->mutex);
|
||||
|
||||
if (rpcn::is_error(static_cast<rpcn::ErrorType>(reply_data[0])))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
vec_stream reply(reply_data, 1);
|
||||
auto raw_getscore_response = reply.get_rawdata();
|
||||
auto* resp = flatbuffers::GetRoot<GetScoreResponse>(raw_getscore_response.data());
|
||||
flatbuffers::Verifier verifier(raw_getscore_response.data(), raw_getscore_response.size());
|
||||
|
||||
if (reply.is_error() || !resp->Verify(verifier))
|
||||
{
|
||||
rpcn_log.error("Error parsing response in reply_record_score");
|
||||
return false;
|
||||
}
|
||||
|
||||
ensure(trans_ctx->data.size() == 7);
|
||||
u32 arrayNum = trans_ctx->data[0];
|
||||
vm::ptr<SceNpScoreRankData> rankArray = vm::cast(trans_ctx->data[1]);
|
||||
vm::ptr<SceNpScoreComment> commentArray = vm::cast(trans_ctx->data[2]);
|
||||
vm::ptr<void> infoArray = vm::cast(trans_ctx->data[3]);
|
||||
bool info_array_is_SceNpScoreGameInfo = trans_ctx->data[4];
|
||||
vm::ptr<CellRtcTick> lastSortDate = vm::cast(trans_ctx->data[5]);
|
||||
vm::ptr<SceNpScoreRankNumber> totalRecord = vm::cast(trans_ctx->data[6]);
|
||||
|
||||
ensure(resp->rankArray() && resp->rankArray()->size() <= arrayNum);
|
||||
|
||||
memset(rankArray.get_ptr(), 0, sizeof(SceNpScoreRankData) * arrayNum);
|
||||
auto* fb_rankarray = resp->rankArray();
|
||||
for (flatbuffers::uoffset_t i = 0; i < fb_rankarray->size(); i++)
|
||||
{
|
||||
const auto* fb_rankdata = fb_rankarray->Get(i);
|
||||
ensure(fb_rankdata->npId() && fb_rankdata->onlineName());
|
||||
string_to_npid(fb_rankdata->npId()->string_view(), &rankArray[i].npId);
|
||||
string_to_online_name(fb_rankdata->onlineName()->string_view(), &rankArray[i].onlineName);
|
||||
rankArray[i].pcId = fb_rankdata->pcId();
|
||||
rankArray[i].serialRank = fb_rankdata->rank();
|
||||
rankArray[i].rank = fb_rankdata->rank();
|
||||
rankArray[i].highestRank = fb_rankdata->rank();
|
||||
rankArray[i].scoreValue = fb_rankdata->score();
|
||||
rankArray[i].hasGameData = fb_rankdata->hasGameData();
|
||||
rankArray[i].recordDate.tick = fb_rankdata->recordDate();
|
||||
}
|
||||
|
||||
if (commentArray)
|
||||
{
|
||||
ensure(resp->commentArray() && resp->commentArray()->size() <= arrayNum);
|
||||
memset(commentArray.get_ptr(), 0, sizeof(SceNpScoreComment) * arrayNum);
|
||||
|
||||
auto* fb_commentarray = resp->commentArray();
|
||||
for (flatbuffers::uoffset_t i = 0; i < fb_commentarray->size(); i++)
|
||||
{
|
||||
const auto* fb_comment = fb_commentarray->Get(i);
|
||||
strcpy_trunc(commentArray[i].data, fb_comment->string_view());
|
||||
}
|
||||
}
|
||||
|
||||
if (infoArray)
|
||||
{
|
||||
ensure(resp->infoArray() && resp->infoArray()->size() <= arrayNum);
|
||||
auto* fb_infoarray = resp->infoArray();
|
||||
|
||||
if (info_array_is_SceNpScoreGameInfo)
|
||||
{
|
||||
vm::ptr<SceNpScoreGameInfo> ptr_gameinfo = vm::static_ptr_cast<SceNpScoreGameInfo>(infoArray);
|
||||
memset(ptr_gameinfo.get_ptr(), 0, sizeof(SceNpScoreGameInfo) * arrayNum);
|
||||
for (flatbuffers::uoffset_t i = 0; i < fb_infoarray->size(); i++)
|
||||
{
|
||||
const auto* fb_info = fb_infoarray->Get(i);
|
||||
ensure(fb_info->data()->size() <= SCE_NP_SCORE_GAMEINFO_SIZE);
|
||||
memcpy(ptr_gameinfo[i].nativeData, fb_info->data()->data(), fb_info->data()->size());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
vm::ptr<SceNpScoreVariableSizeGameInfo> ptr_vargameinfo = vm::static_ptr_cast<SceNpScoreVariableSizeGameInfo>(infoArray);
|
||||
memset(ptr_vargameinfo.get_ptr(), 0, sizeof(SceNpScoreVariableSizeGameInfo) * arrayNum);
|
||||
for (flatbuffers::uoffset_t i = 0; i < fb_infoarray->size(); i++)
|
||||
{
|
||||
const auto* fb_info = fb_infoarray->Get(i);
|
||||
ensure(fb_info->data()->size() <= SCE_NP_SCORE_VARIABLE_SIZE_GAMEINFO_MAXSIZE);
|
||||
ptr_vargameinfo[i].infoSize = fb_info->data()->size();
|
||||
memcpy(ptr_vargameinfo[i].data, fb_info->data(), fb_info->data()->size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lastSortDate->tick = resp->lastSortDate();
|
||||
*totalRecord = resp->totalRecord();
|
||||
|
||||
trans_ctx->result = not_an_error(fb_rankarray->size());
|
||||
trans_ctx->wake_cond.notify_one();
|
||||
return true;
|
||||
}
|
||||
bool np_handler::reply_get_score_range(u32 req_id, std::vector<u8>& reply_data)
|
||||
{
|
||||
return handle_GetScoreResponse(req_id, reply_data);
|
||||
}
|
||||
|
||||
void np_handler::get_score_friend(std::shared_ptr<score_transaction_ctx>& trans_ctx, SceNpScoreBoardId boardId, vm::ptr<SceNpScoreRankData> rankArray, [[maybe_unused]] u64 rankArraySize, vm::ptr<SceNpScoreComment> commentArray, [[maybe_unused]] u64 commentArraySize, vm::ptr<void> infoArray, u64 infoArraySize, u64 arrayNum, vm::ptr<CellRtcTick> lastSortDate, vm::ptr<SceNpScoreRankNumber> totalRecord, bool async)
|
||||
{
|
||||
std::unique_lock lock(trans_ctx->mutex);
|
||||
u32 req_id = get_req_id(0x3334);
|
||||
trans_ctx->data.clear();
|
||||
trans_ctx->data.push_back(static_cast<u32>(arrayNum));
|
||||
trans_ctx->data.push_back(rankArray.addr());
|
||||
trans_ctx->data.push_back(commentArray.addr());
|
||||
trans_ctx->data.push_back(infoArray.addr());
|
||||
trans_ctx->data.push_back(static_cast<u32>((arrayNum * sizeof(SceNpScoreGameInfo)) == infoArraySize));
|
||||
trans_ctx->data.push_back(lastSortDate.addr());
|
||||
trans_ctx->data.push_back(totalRecord.addr());
|
||||
|
||||
bool with_comments = !!commentArray;
|
||||
bool with_gameinfo = !!infoArray;
|
||||
|
||||
rpcn->get_score_friend(req_id, trans_ctx->communicationId, boardId, with_comments, with_gameinfo);
|
||||
|
||||
return score_async_handler(std::move(lock), trans_ctx, req_id, async);
|
||||
}
|
||||
bool np_handler::reply_get_score_friends(u32 req_id, std::vector<u8>& reply_data)
|
||||
{
|
||||
return handle_GetScoreResponse(req_id, reply_data);
|
||||
}
|
||||
|
||||
void np_handler::get_score_npid(std::shared_ptr<score_transaction_ctx>& trans_ctx, SceNpScoreBoardId boardId, const std::vector<std::pair<SceNpId, s32>>& npid_vec, vm::ptr<SceNpScorePlayerRankData> rankArray, [[maybe_unused]] u64 rankArraySize, vm::ptr<SceNpScoreComment> commentArray, [[maybe_unused]] u64 commentArraySize, vm::ptr<void> infoArray, u64 infoArraySize, u64 arrayNum, vm::ptr<CellRtcTick> lastSortDate, vm::ptr<SceNpScoreRankNumber> totalRecord, bool async)
|
||||
{
|
||||
std::unique_lock lock(trans_ctx->mutex);
|
||||
u32 req_id = get_req_id(0x3334);
|
||||
trans_ctx->data.clear();
|
||||
trans_ctx->data.push_back(static_cast<u32>(arrayNum));
|
||||
trans_ctx->data.push_back(rankArray.addr());
|
||||
trans_ctx->data.push_back(commentArray.addr());
|
||||
trans_ctx->data.push_back(infoArray.addr());
|
||||
trans_ctx->data.push_back(static_cast<u32>((arrayNum * sizeof(SceNpScoreGameInfo)) == infoArraySize));
|
||||
trans_ctx->data.push_back(lastSortDate.addr());
|
||||
trans_ctx->data.push_back(totalRecord.addr());
|
||||
|
||||
bool with_comments = !!commentArray;
|
||||
bool with_gameinfo = !!infoArray;
|
||||
|
||||
rpcn->get_score_npid(req_id, trans_ctx->communicationId, boardId, npid_vec, with_comments, with_gameinfo);
|
||||
|
||||
return score_async_handler(std::move(lock), trans_ctx, req_id, async);
|
||||
}
|
||||
bool np_handler::reply_get_score_npid(u32 req_id, std::vector<u8>& reply_data)
|
||||
{
|
||||
return handle_GetScoreResponse(req_id, reply_data);
|
||||
}
|
||||
|
||||
} // namespace np
|
||||
|
@ -8,6 +8,14 @@ LOG_CHANNEL(sceNp2);
|
||||
|
||||
namespace extra_nps
|
||||
{
|
||||
void print_userinfo2(const SceNpUserInfo2* user)
|
||||
{
|
||||
sceNp2.warning("SceNpUserInfo2:");
|
||||
sceNp2.warning("npid: %s", static_cast<const char*>(user->npId.handle.data));
|
||||
sceNp2.warning("onlineName: *0x%x(%s)", user->onlineName, user->onlineName ? static_cast<const char*>(user->onlineName->data) : "");
|
||||
sceNp2.warning("avatarUrl: *0x%x(%s)", user->avatarUrl, user->avatarUrl ? static_cast<const char*>(user->avatarUrl->data) : "");
|
||||
}
|
||||
|
||||
void print_sigoptparam(const SceNpMatching2SignalingOptParam* opt)
|
||||
{
|
||||
sceNp2.warning("type: %d", opt->type);
|
||||
@ -49,6 +57,13 @@ namespace extra_nps
|
||||
sceNp2.warning("Data: %s", dadata);
|
||||
}
|
||||
|
||||
void print_range(const SceNpMatching2Range* range)
|
||||
{
|
||||
sceNp2.warning("startIndex: %d", range->startIndex);
|
||||
sceNp2.warning("total: %d", range->total);
|
||||
sceNp2.warning("size: %d", range->size);
|
||||
}
|
||||
|
||||
void print_range_filter(const SceNpMatching2RangeFilter* filt)
|
||||
{
|
||||
sceNp2.warning("startIndex: %d", filt->startIndex);
|
||||
@ -133,6 +148,20 @@ namespace extra_nps
|
||||
sceNp2.warning("attrIdNum: %d", req->attrIdNum);
|
||||
}
|
||||
|
||||
void print_search_room_resp(const SceNpMatching2SearchRoomResponse* resp)
|
||||
{
|
||||
sceNp2.warning("SceNpMatching2SearchRoomResponse:");
|
||||
print_range(&resp->range);
|
||||
|
||||
const SceNpMatching2RoomDataExternal *room_ptr = resp->roomDataExternal.get_ptr();
|
||||
for (u32 i = 0; i < resp->range.total; i++)
|
||||
{
|
||||
sceNp2.warning("SceNpMatching2SearchRoomResponse[%d]:", i);
|
||||
print_room_data_external(room_ptr);
|
||||
room_ptr = room_ptr->next.get_ptr();
|
||||
}
|
||||
}
|
||||
|
||||
void print_room_member_data_internal(const SceNpMatching2RoomMemberDataInternal* member)
|
||||
{
|
||||
sceNp2.warning("SceNpMatching2RoomMemberDataInternal:");
|
||||
@ -182,6 +211,38 @@ namespace extra_nps
|
||||
print_bin_attr_internal(&room->roomBinAttrInternal[i]);
|
||||
}
|
||||
|
||||
void print_room_data_external(const SceNpMatching2RoomDataExternal* room)
|
||||
{
|
||||
sceNp2.warning("SceNpMatching2RoomDataExternal:");
|
||||
sceNp2.warning("next: *0x%x", room->next);
|
||||
sceNp2.warning("serverId: %d", room->serverId);
|
||||
sceNp2.warning("worldId: %d", room->worldId);
|
||||
sceNp2.warning("publicSlotNum: %d", room->publicSlotNum);
|
||||
sceNp2.warning("privateSlotNum: %d", room->privateSlotNum);
|
||||
sceNp2.warning("lobbyId: %d", room->lobbyId);
|
||||
sceNp2.warning("roomId: %d", room->roomId);
|
||||
sceNp2.warning("openPublicSlotNum: %d", room->openPublicSlotNum);
|
||||
sceNp2.warning("maxSlot: %d", room->maxSlot);
|
||||
sceNp2.warning("openPrivateSlotNum: %d", room->openPrivateSlotNum);
|
||||
sceNp2.warning("curMemberNum: %d", room->curMemberNum);
|
||||
sceNp2.warning("SceNpMatching2RoomPasswordSlotMask: 0x%x", room->passwordSlotMask);
|
||||
sceNp2.warning("owner: *0x%x", room->owner);
|
||||
print_userinfo2(room->owner.get_ptr());
|
||||
sceNp2.warning("roomGroup: *0x%x", room->roomGroup);
|
||||
// TODO: print roomGroup
|
||||
sceNp2.warning("roomGroupNum: %d", room->roomGroupNum);
|
||||
sceNp2.warning("flagAttr: 0x%x", room->flagAttr);
|
||||
sceNp2.warning("roomSearchableIntAttrExternal: *0x%x", room->roomSearchableIntAttrExternal);
|
||||
sceNp2.warning("roomSearchableIntAttrExternalNum: %d", room->roomSearchableIntAttrExternalNum);
|
||||
// TODO: print roomSearchableIntAttrExternal
|
||||
sceNp2.warning("roomSearchableBinAttrExternal: *0x%x", room->roomSearchableBinAttrExternal);
|
||||
sceNp2.warning("roomSearchableBinAttrExternalNum: %d", room->roomSearchableBinAttrExternalNum);
|
||||
// TODO: print roomSearchableBinAttrExternal
|
||||
sceNp2.warning("roomBinAttrExternal: *0x%x", room->roomBinAttrExternal);
|
||||
sceNp2.warning("roomBinAttrExternalNum: %d", room->roomBinAttrExternalNum);
|
||||
// TODO: print roomBinAttrExternal
|
||||
}
|
||||
|
||||
void print_create_room_resp(const SceNpMatching2CreateJoinRoomResponse* resp)
|
||||
{
|
||||
sceNp2.warning("SceNpMatching2CreateJoinRoomResponse:");
|
||||
@ -231,4 +292,37 @@ namespace extra_nps
|
||||
print_bin_attr(&req->roomMemberBinAttrInternal[i]);
|
||||
}
|
||||
|
||||
void print_get_roomdata_external_list_req(const SceNpMatching2GetRoomDataExternalListRequest* req)
|
||||
{
|
||||
sceNp2.warning("SceNpMatching2GetRoomDataExternalListRequest:");
|
||||
sceNp2.warning("roomId: *0x%x", req->roomId);
|
||||
sceNp2.warning("roomIdNum: %d", req->roomIdNum);
|
||||
for (u32 i = 0; i < req->roomIdNum; i++)
|
||||
{
|
||||
sceNp2.warning("RoomId[%d] = %d", i, req->roomId[i]);
|
||||
}
|
||||
sceNp2.warning("attrId: *0x%x", req->attrId);
|
||||
sceNp2.warning("attrIdNum: %d", req->attrIdNum);
|
||||
for (u32 i = 0; i < req->attrIdNum; i++)
|
||||
{
|
||||
sceNp2.warning("attrId[%d] = %d", i, req->attrId[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void print_get_roomdata_external_list_resp(const SceNpMatching2GetRoomDataExternalListResponse* resp)
|
||||
{
|
||||
sceNp2.warning("SceNpMatching2GetRoomDataExternalListResponse:");
|
||||
sceNp2.warning("roomDataExternal: *0x%x", resp->roomDataExternal);
|
||||
sceNp2.warning("roomDataExternalNum: %d", resp->roomDataExternalNum);
|
||||
|
||||
const SceNpMatching2RoomDataExternal* cur_room = resp->roomDataExternal.get_ptr();
|
||||
|
||||
for (u32 i = 0; i < resp->roomDataExternalNum; i++)
|
||||
{
|
||||
sceNp2.warning("SceNpMatching2GetRoomDataExternalListResponse[%d]:", i);
|
||||
print_room_data_external(cur_room);
|
||||
cur_room = cur_room->next.get_ptr();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace extra_nps
|
||||
|
@ -4,18 +4,23 @@
|
||||
|
||||
namespace extra_nps
|
||||
{
|
||||
void print_userinfo2(const SceNpUserInfo2* user);
|
||||
void print_sigoptparam(const SceNpMatching2SignalingOptParam* opt);
|
||||
void print_bin_attr(const SceNpMatching2BinAttr* bin);
|
||||
void print_presence_data(const SceNpMatching2PresenceOptionData* opt);
|
||||
void print_range_filter(const SceNpMatching2RangeFilter* filt);
|
||||
void print_room_data_internal(const SceNpMatching2RoomDataInternal* room);
|
||||
void print_room_data_external(const SceNpMatching2RoomDataExternal* room);
|
||||
void print_room_member_data_internal(const SceNpMatching2RoomMemberDataInternal* member);
|
||||
|
||||
void print_createjoinroom(const SceNpMatching2CreateJoinRoomRequest* req);
|
||||
void print_create_room_resp(const SceNpMatching2CreateJoinRoomResponse* resp);
|
||||
void print_joinroom(const SceNpMatching2JoinRoomRequest* req);
|
||||
void print_search_room(const SceNpMatching2SearchRoomRequest* req);
|
||||
void print_search_room_resp(const SceNpMatching2SearchRoomResponse* resp);
|
||||
void print_set_roomdata_ext_req(const SceNpMatching2SetRoomDataExternalRequest* req);
|
||||
void print_set_roomdata_int_req(const SceNpMatching2SetRoomDataInternalRequest* req);
|
||||
void print_set_roommemberdata_int_req(const SceNpMatching2SetRoomMemberDataInternalRequest* req);
|
||||
void print_get_roomdata_external_list_req(const SceNpMatching2GetRoomDataExternalListRequest* req);
|
||||
void print_get_roomdata_external_list_resp(const SceNpMatching2GetRoomDataExternalListResponse* resp);
|
||||
} // namespace extra_nps
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/NP/rpcn_config.h"
|
||||
#include "Emu/NP/np_helpers.h"
|
||||
#include "Emu/NP/vport0.h"
|
||||
|
||||
#include "util/asm.hpp"
|
||||
|
||||
@ -43,10 +44,6 @@
|
||||
|
||||
LOG_CHANNEL(rpcn_log, "rpcn");
|
||||
|
||||
// Those are defined here to avoid including sys_net.h
|
||||
s32 send_packet_from_p2p_port(const std::vector<u8>& data, const sockaddr_in& addr);
|
||||
std::vector<std::vector<u8>> get_rpcn_msgs();
|
||||
|
||||
namespace rpcn
|
||||
{
|
||||
localized_string_id rpcn_state_to_localized_string_id(rpcn::rpcn_state state)
|
||||
@ -74,10 +71,49 @@ namespace rpcn
|
||||
return get_localized_string(rpcn_state_to_localized_string_id(state));
|
||||
}
|
||||
|
||||
constexpr u32 RPCN_PROTOCOL_VERSION = 15;
|
||||
constexpr usz RPCN_HEADER_SIZE = 13;
|
||||
constexpr u32 RPCN_PROTOCOL_VERSION = 16;
|
||||
constexpr usz RPCN_HEADER_SIZE = 15;
|
||||
constexpr usz COMMUNICATION_ID_SIZE = 9;
|
||||
|
||||
bool is_error(ErrorType err)
|
||||
{
|
||||
if (err >= ErrorType::__error_last)
|
||||
{
|
||||
rpcn_log.error("Invalid error returned!");
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (err)
|
||||
{
|
||||
case NoError: return false;
|
||||
case Malformed: rpcn_log.error("Sent packet was malformed!"); break;
|
||||
case Invalid: rpcn_log.error("Sent command was invalid!"); break;
|
||||
case InvalidInput: rpcn_log.error("Sent data was invalid!"); break;
|
||||
case TooSoon: rpcn_log.error("Request happened too soon!"); break;
|
||||
case LoginError: rpcn_log.error("Unknown login error!"); break;
|
||||
case LoginAlreadyLoggedIn: rpcn_log.error("User is already logged in!"); break;
|
||||
case LoginInvalidUsername: rpcn_log.error("Login error: invalid username!"); break;
|
||||
case LoginInvalidPassword: rpcn_log.error("Login error: invalid password!"); break;
|
||||
case LoginInvalidToken: rpcn_log.error("Login error: invalid token!"); break;
|
||||
case CreationError: rpcn_log.error("Error creating an account!"); break;
|
||||
case CreationExistingUsername: rpcn_log.error("Error creating an account: existing username!"); break;
|
||||
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!"); 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;
|
||||
case Blocked: rpcn_log.error("You're blocked!"); break;
|
||||
case AlreadyFriend: rpcn_log.error("You're already friends!"); break;
|
||||
case ScoreNotBest: rpcn_log.error("Attempted to register a score that is not better!"); break;
|
||||
case Unsupported: rpcn_log.error("An unsupported operation was attempted!"); break;
|
||||
default: rpcn_log.fatal("Unhandled ErrorType reached the switch?"); break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Constructor, destructor & singleton manager
|
||||
|
||||
rpcn_client::rpcn_client()
|
||||
@ -198,6 +234,7 @@ namespace rpcn
|
||||
{
|
||||
if (want_conn)
|
||||
{
|
||||
want_conn = false;
|
||||
{
|
||||
std::lock_guard lock(mutex_connected);
|
||||
connect(g_cfg_rpcn.get_host());
|
||||
@ -257,9 +294,10 @@ namespace rpcn
|
||||
// Send a packet every 5 seconds and then every 500 ms until reply is received
|
||||
if (now - last_pong_time >= 5s && now - last_ping_time > 500ms)
|
||||
{
|
||||
std::vector<u8> ping(9);
|
||||
std::vector<u8> ping(13);
|
||||
ping[0] = 1;
|
||||
*utils::bless<le_t<s64, 1>>(&ping[1]) = user_id;
|
||||
*utils::bless<be_t<u32, 1>>(&ping[9]) = local_addr_sig;
|
||||
if (send_packet_from_p2p_port(ping, addr_rpcn_udp) == -1)
|
||||
{
|
||||
rpcn_log.error("Failed to send ping to rpcn!");
|
||||
@ -301,8 +339,8 @@ namespace rpcn
|
||||
|
||||
const u8 packet_type = header[0];
|
||||
const u16 command = *utils::bless<le_t<u16>>(&header[1]);
|
||||
const u16 packet_size = *utils::bless<le_t<u16>>(&header[3]);
|
||||
const u64 packet_id = *utils::bless<le_t<u64>>(&header[5]);
|
||||
const u32 packet_size = *utils::bless<le_t<u32>>(&header[3]);
|
||||
const u64 packet_id = *utils::bless<le_t<u64>>(&header[7]);
|
||||
|
||||
if (packet_size < RPCN_HEADER_SIZE)
|
||||
return error_and_disconnect("Invalid packet size");
|
||||
@ -328,7 +366,8 @@ namespace rpcn
|
||||
if (command == CommandType::Login || command == CommandType::GetServerList || command == CommandType::Create ||
|
||||
command == CommandType::AddFriend || command == CommandType::RemoveFriend ||
|
||||
command == CommandType::AddBlock || command == CommandType::RemoveBlock ||
|
||||
command == CommandType::SendMessage || command == CommandType::SendToken)
|
||||
command == CommandType::SendMessage || command == CommandType::SendToken ||
|
||||
command == CommandType::SendResetToken || command == CommandType::ResetPassword)
|
||||
{
|
||||
std::lock_guard lock(mutex_replies_sync);
|
||||
replies_sync.insert(std::make_pair(packet_id, std::make_pair(command, std::move(data))));
|
||||
@ -681,6 +720,16 @@ namespace rpcn
|
||||
|
||||
rpcn_log.notice("connect: Connection successful");
|
||||
|
||||
sockaddr_in client_addr;
|
||||
socklen_t client_addr_size = sizeof(client_addr);
|
||||
if (getsockname(sockfd, reinterpret_cast<struct sockaddr*>(&client_addr), &client_addr_size) != 0)
|
||||
{
|
||||
rpcn_log.error("Failed to get the client address from the socket!");
|
||||
}
|
||||
|
||||
update_local_addr(client_addr.sin_addr.s_addr);
|
||||
rpcn_log.notice("Updated local address to %s", np::ip_to_string(std::bit_cast<u32, be_t<u32>>(local_addr_sig.load())));
|
||||
|
||||
if (wolfSSL_set_fd(read_wssl, sockfd) != WOLFSSL_SUCCESS)
|
||||
{
|
||||
rpcn_log.error("connect: Failed to associate wolfssl to the socket");
|
||||
@ -837,7 +886,7 @@ namespace rpcn
|
||||
return true;
|
||||
}
|
||||
|
||||
ErrorType rpcn_client::create_user(const std::string& npid, const std::string& password, const std::string& online_name, const std::string& avatar_url, const std::string& email)
|
||||
ErrorType rpcn_client::create_user(std::string_view npid, std::string_view password, std::string_view online_name, std::string_view avatar_url, std::string_view email)
|
||||
{
|
||||
std::vector<u8> data;
|
||||
std::copy(npid.begin(), npid.end(), std::back_inserter(data));
|
||||
@ -908,6 +957,78 @@ namespace rpcn
|
||||
return ErrorType::NoError;
|
||||
}
|
||||
|
||||
ErrorType rpcn_client::send_reset_token(std::string_view npid, std::string_view email)
|
||||
{
|
||||
if (authentified)
|
||||
{
|
||||
// If you're already logged in why do you need a password reset token?
|
||||
return ErrorType::LoginAlreadyLoggedIn;
|
||||
}
|
||||
|
||||
std::vector<u8> data;
|
||||
std::copy(npid.begin(), npid.end(), std::back_inserter(data));
|
||||
data.push_back(0);
|
||||
std::copy(email.begin(), email.end(), std::back_inserter(data));
|
||||
data.push_back(0);
|
||||
|
||||
u64 req_id = rpcn_request_counter.fetch_add(1);
|
||||
|
||||
std::vector<u8> packet_data;
|
||||
if (!forge_send_reply(CommandType::SendResetToken, req_id, data, packet_data))
|
||||
{
|
||||
return ErrorType::Malformed;
|
||||
}
|
||||
|
||||
vec_stream reply(packet_data);
|
||||
auto error = static_cast<ErrorType>(reply.get<u8>());
|
||||
|
||||
if (is_error(error))
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
rpcn_log.success("Password reset token has successfully been sent!");
|
||||
|
||||
return ErrorType::NoError;
|
||||
}
|
||||
|
||||
ErrorType rpcn_client::reset_password(std::string_view npid, std::string_view token, std::string_view password)
|
||||
{
|
||||
if (authentified)
|
||||
{
|
||||
// If you're already logged in why do you need to reset the password?
|
||||
return ErrorType::LoginAlreadyLoggedIn;
|
||||
}
|
||||
|
||||
std::vector<u8> data;
|
||||
std::copy(npid.begin(), npid.end(), std::back_inserter(data));
|
||||
data.push_back(0);
|
||||
std::copy(token.begin(), token.end(), std::back_inserter(data));
|
||||
data.push_back(0);
|
||||
std::copy(password.begin(), password.end(), std::back_inserter(data));
|
||||
data.push_back(0);
|
||||
|
||||
u64 req_id = rpcn_request_counter.fetch_add(1);
|
||||
|
||||
std::vector<u8> packet_data;
|
||||
if (!forge_send_reply(CommandType::ResetPassword, req_id, data, packet_data))
|
||||
{
|
||||
return ErrorType::Malformed;
|
||||
}
|
||||
|
||||
vec_stream reply(packet_data);
|
||||
auto error = static_cast<ErrorType>(reply.get<u8>());
|
||||
|
||||
if (is_error(error))
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
rpcn_log.success("Password has successfully been reset!");
|
||||
|
||||
return ErrorType::NoError;
|
||||
}
|
||||
|
||||
bool rpcn_client::add_friend(const std::string& friend_username)
|
||||
{
|
||||
std::vector<u8> data;
|
||||
@ -1067,18 +1188,13 @@ namespace rpcn
|
||||
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
|
||||
reinterpret_cast<le_t<u16>&>(data[COMMUNICATION_ID_SIZE]) = server_id;
|
||||
|
||||
if (!forge_send(CommandType::GetWorldList, req_id, data))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
return forge_send(CommandType::GetWorldList, req_id, data);
|
||||
}
|
||||
|
||||
bool rpcn_client::createjoin_room(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2CreateJoinRoomRequest* req)
|
||||
{
|
||||
std::vector<u8> data;
|
||||
|
||||
extra_nps::print_createjoinroom(req);
|
||||
|
||||
flatbuffers::FlatBufferBuilder builder(1024);
|
||||
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<BinAttr>>> final_binattrinternal_vec;
|
||||
@ -1196,18 +1312,13 @@ namespace rpcn
|
||||
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
|
||||
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
|
||||
|
||||
if (!forge_send(CommandType::CreateRoom, req_id, data))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
return forge_send(CommandType::CreateRoom, req_id, data);
|
||||
}
|
||||
|
||||
bool rpcn_client::join_room(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2JoinRoomRequest* req)
|
||||
{
|
||||
std::vector<u8> data;
|
||||
|
||||
extra_nps::print_joinroom(req);
|
||||
|
||||
flatbuffers::FlatBufferBuilder builder(1024);
|
||||
|
||||
flatbuffers::Offset<flatbuffers::Vector<u8>> final_roompassword;
|
||||
@ -1240,10 +1351,7 @@ namespace rpcn
|
||||
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
|
||||
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
|
||||
|
||||
if (!forge_send(CommandType::JoinRoom, req_id, data))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
return forge_send(CommandType::JoinRoom, req_id, data);
|
||||
}
|
||||
|
||||
bool rpcn_client::leave_room(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2LeaveRoomRequest* req)
|
||||
@ -1262,18 +1370,13 @@ namespace rpcn
|
||||
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
|
||||
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
|
||||
|
||||
if (!forge_send(CommandType::LeaveRoom, req_id, data))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
return forge_send(CommandType::LeaveRoom, req_id, data);
|
||||
}
|
||||
|
||||
bool rpcn_client::search_room(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2SearchRoomRequest* req)
|
||||
{
|
||||
std::vector<u8> data;
|
||||
|
||||
extra_nps::print_search_room(req);
|
||||
|
||||
flatbuffers::FlatBufferBuilder builder(1024);
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<IntSearchFilter>>> final_intfilter_vec;
|
||||
if (req->intFilterNum)
|
||||
@ -1299,9 +1402,17 @@ namespace rpcn
|
||||
}
|
||||
final_binfilter_vec = builder.CreateVector(davec);
|
||||
}
|
||||
|
||||
flatbuffers::Offset<flatbuffers::Vector<u16>> attrid_vec;
|
||||
if (req->attrIdNum)
|
||||
attrid_vec = builder.CreateVector(utils::bless<const u16>(req->attrId.get_ptr()), req->attrIdNum);
|
||||
{
|
||||
std::vector<u16> attr_ids;
|
||||
for (u32 i = 0; i < req->attrIdNum; i++)
|
||||
{
|
||||
attr_ids.push_back(req->attrId[i]);
|
||||
}
|
||||
attrid_vec = builder.CreateVector(attr_ids);
|
||||
}
|
||||
|
||||
SearchRoomRequestBuilder s_req(builder);
|
||||
s_req.add_option(req->option);
|
||||
@ -1328,10 +1439,7 @@ namespace rpcn
|
||||
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
|
||||
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
|
||||
|
||||
if (!forge_send(CommandType::SearchRoom, req_id, data))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
return forge_send(CommandType::SearchRoom, req_id, data);
|
||||
}
|
||||
|
||||
bool rpcn_client::get_roomdata_external_list(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2GetRoomDataExternalListRequest* req)
|
||||
@ -1361,10 +1469,7 @@ namespace rpcn
|
||||
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
|
||||
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
|
||||
|
||||
if (!forge_send(CommandType::GetRoomDataExternalList, req_id, data))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
return forge_send(CommandType::GetRoomDataExternalList, req_id, data);
|
||||
}
|
||||
|
||||
bool rpcn_client::set_roomdata_external(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2SetRoomDataExternalRequest* req)
|
||||
@ -1416,10 +1521,7 @@ namespace rpcn
|
||||
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
|
||||
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
|
||||
|
||||
if (!forge_send(CommandType::SetRoomDataExternal, req_id, data))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
return forge_send(CommandType::SetRoomDataExternal, req_id, data);
|
||||
}
|
||||
|
||||
bool rpcn_client::get_roomdata_internal(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2GetRoomDataInternalRequest* req)
|
||||
@ -1430,7 +1532,14 @@ namespace rpcn
|
||||
|
||||
flatbuffers::Offset<flatbuffers::Vector<u16>> final_attr_ids_vec;
|
||||
if (req->attrIdNum)
|
||||
final_attr_ids_vec = builder.CreateVector(utils::bless<const u16>(req->attrId.get_ptr()), req->attrIdNum);
|
||||
{
|
||||
std::vector<u16> attr_ids;
|
||||
for (u32 i = 0; i < req->attrIdNum; i++)
|
||||
{
|
||||
attr_ids.push_back(req->attrId[i]);
|
||||
}
|
||||
final_attr_ids_vec = builder.CreateVector(attr_ids);
|
||||
}
|
||||
|
||||
auto req_finished = CreateGetRoomDataInternalRequest(builder, req->roomId, final_attr_ids_vec);
|
||||
|
||||
@ -1443,18 +1552,13 @@ namespace rpcn
|
||||
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
|
||||
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
|
||||
|
||||
if (!forge_send(CommandType::GetRoomDataInternal, req_id, data))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
return forge_send(CommandType::GetRoomDataInternal, req_id, data);
|
||||
}
|
||||
|
||||
bool rpcn_client::set_roomdata_internal(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2SetRoomDataInternalRequest* req)
|
||||
{
|
||||
std::vector<u8> data;
|
||||
|
||||
// extra_nps::print_set_roomdata_req(req);
|
||||
|
||||
flatbuffers::FlatBufferBuilder builder(1024);
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<BinAttr>>> final_binattrinternal_vec;
|
||||
if (req->roomBinAttrInternalNum)
|
||||
@ -1484,7 +1588,14 @@ namespace rpcn
|
||||
|
||||
flatbuffers::Offset<flatbuffers::Vector<u16>> final_ownerprivilege_vec;
|
||||
if (req->ownerPrivilegeRankNum)
|
||||
final_ownerprivilege_vec = builder.CreateVector(utils::bless<const u16>(req->ownerPrivilegeRank.get_ptr()), req->ownerPrivilegeRankNum);
|
||||
{
|
||||
std::vector<u16> priv_ranks;
|
||||
for (u32 i = 0; i < req->ownerPrivilegeRankNum; i++)
|
||||
{
|
||||
priv_ranks.push_back(req->ownerPrivilegeRank[i]);
|
||||
}
|
||||
final_ownerprivilege_vec = builder.CreateVector(priv_ranks);
|
||||
}
|
||||
|
||||
auto req_finished =
|
||||
CreateSetRoomDataInternalRequest(builder, req->roomId, req->flagFilter, req->flagAttr, final_binattrinternal_vec, final_grouppasswordconfig_vec, final_passwordSlotMask, final_ownerprivilege_vec);
|
||||
@ -1498,18 +1609,13 @@ namespace rpcn
|
||||
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
|
||||
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
|
||||
|
||||
if (!forge_send(CommandType::SetRoomDataInternal, req_id, data))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
return forge_send(CommandType::SetRoomDataInternal, req_id, data);
|
||||
}
|
||||
|
||||
bool rpcn_client::set_roommemberdata_internal(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2SetRoomMemberDataInternalRequest* req)
|
||||
{
|
||||
std::vector<u8> data{};
|
||||
|
||||
extra_nps::print_set_roommemberdata_int_req(req);
|
||||
|
||||
flatbuffers::FlatBufferBuilder builder(1024);
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<BinAttr>>> final_binattrinternal_vec;
|
||||
if (req->roomMemberBinAttrInternalNum)
|
||||
@ -1534,10 +1640,7 @@ namespace rpcn
|
||||
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
|
||||
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
|
||||
|
||||
if (!forge_send(CommandType::SetRoomMemberDataInternal, req_id, data))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
return forge_send(CommandType::SetRoomMemberDataInternal, req_id, data);
|
||||
}
|
||||
|
||||
bool rpcn_client::ping_room_owner(u32 req_id, const SceNpCommunicationId& communication_id, u64 room_id)
|
||||
@ -1549,10 +1652,7 @@ namespace rpcn
|
||||
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
|
||||
*utils::bless<le_t<u64>>(&data[COMMUNICATION_ID_SIZE]) = room_id;
|
||||
|
||||
if (!forge_send(CommandType::PingRoomOwner, req_id, data))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
return forge_send(CommandType::PingRoomOwner, req_id, data);
|
||||
}
|
||||
|
||||
bool rpcn_client::send_room_message(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2SendRoomMessageRequest* req)
|
||||
@ -1587,16 +1687,13 @@ namespace rpcn
|
||||
builder.Finish(req_finished);
|
||||
u8* buf = builder.GetBufferPointer();
|
||||
usz bufsize = builder.GetSize();
|
||||
data.resize(COMMUNICATION_ID_SIZE + bufsize + sizeof(u32));
|
||||
data.resize(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
|
||||
|
||||
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
|
||||
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
|
||||
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
|
||||
|
||||
if (!forge_send(CommandType::SendRoomMessage, req_id, data))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
return forge_send(CommandType::SendRoomMessage, req_id, data);
|
||||
}
|
||||
|
||||
bool rpcn_client::req_sign_infos(u32 req_id, const std::string& npid)
|
||||
@ -1605,10 +1702,7 @@ namespace rpcn
|
||||
std::copy(npid.begin(), npid.end(), std::back_inserter(data));
|
||||
data.push_back(0);
|
||||
|
||||
if (!forge_send(CommandType::RequestSignalingInfos, req_id, data))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
return forge_send(CommandType::RequestSignalingInfos, req_id, data);
|
||||
}
|
||||
|
||||
bool rpcn_client::req_ticket(u32 req_id, const std::string& service_id, const std::vector<u8>& cookie)
|
||||
@ -1620,10 +1714,7 @@ namespace rpcn
|
||||
std::copy(reinterpret_cast<const u8*>(&size), reinterpret_cast<const u8*>(&size) + sizeof(le_t<u32>), std::back_inserter(data));
|
||||
std::copy(cookie.begin(), cookie.end(), std::back_inserter(data));
|
||||
|
||||
if (!forge_send(CommandType::RequestTicket, req_id, data))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
return forge_send(CommandType::RequestTicket, req_id, data);
|
||||
}
|
||||
|
||||
bool rpcn_client::sendmessage(const message_data& msg_data, const std::set<std::string>& npids)
|
||||
@ -1658,64 +1749,113 @@ namespace rpcn
|
||||
|
||||
u64 req_id = rpcn_request_counter.fetch_add(1);
|
||||
|
||||
if (!forge_send(CommandType::SendMessage, req_id, data))
|
||||
return false;
|
||||
return forge_send(CommandType::SendMessage, req_id, data);
|
||||
}
|
||||
|
||||
return true;
|
||||
bool rpcn_client::get_board_infos(u32 req_id, const SceNpCommunicationId& communication_id, SceNpScoreBoardId board_id)
|
||||
{
|
||||
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u32));
|
||||
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
|
||||
*utils::bless<le_t<u32>>(&data[COMMUNICATION_ID_SIZE]) = board_id;
|
||||
|
||||
return forge_send(CommandType::GetBoardInfos, req_id, data);
|
||||
}
|
||||
|
||||
bool rpcn_client::record_score(u32 req_id, const SceNpCommunicationId& communication_id, SceNpScoreBoardId board_id, SceNpScorePcId char_id, SceNpScoreValue score, const std::optional<std::string> comment, const std::optional<std::vector<u8>> score_data)
|
||||
{
|
||||
std::vector<u8> data;
|
||||
flatbuffers::FlatBufferBuilder builder(1024);
|
||||
|
||||
auto req_finished = CreateRecordScoreRequestDirect(builder, board_id, char_id, score, comment ? (*comment).c_str() : nullptr, score_data ? &*score_data : nullptr);
|
||||
|
||||
builder.Finish(req_finished);
|
||||
u8* buf = builder.GetBufferPointer();
|
||||
usz bufsize = builder.GetSize();
|
||||
data.resize(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
|
||||
|
||||
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
|
||||
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
|
||||
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
|
||||
|
||||
return forge_send(CommandType::RecordScore, req_id, data);
|
||||
}
|
||||
|
||||
bool rpcn_client::get_score_range(u32 req_id, const SceNpCommunicationId& communication_id, SceNpScoreBoardId board_id, u32 start_rank, u32 num_rank, bool with_comment, bool with_gameinfo)
|
||||
{
|
||||
std::vector<u8> data;
|
||||
flatbuffers::FlatBufferBuilder builder(1024);
|
||||
auto req_finished = CreateGetScoreRangeRequest(builder, board_id, start_rank, num_rank, with_comment, with_gameinfo);
|
||||
|
||||
builder.Finish(req_finished);
|
||||
u8* buf = builder.GetBufferPointer();
|
||||
usz bufsize = builder.GetSize();
|
||||
data.resize(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
|
||||
|
||||
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
|
||||
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
|
||||
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
|
||||
|
||||
return forge_send(CommandType::GetScoreRange, req_id, data);
|
||||
}
|
||||
|
||||
bool rpcn_client::get_score_npid(u32 req_id, const SceNpCommunicationId& communication_id, SceNpScoreBoardId board_id, const std::vector<std::pair<SceNpId, s32>>& npids, bool with_comment, bool with_gameinfo)
|
||||
{
|
||||
std::vector<u8> data;
|
||||
flatbuffers::FlatBufferBuilder builder(1024);
|
||||
|
||||
std::vector<flatbuffers::Offset<ScoreNpIdPcId>> davec;
|
||||
for (usz i = 0; i < npids.size(); i++)
|
||||
{
|
||||
auto npid = CreateScoreNpIdPcId(builder, builder.CreateString(static_cast<const char*>(npids[i].first.handle.data)), npids[i].second);
|
||||
davec.push_back(npid);
|
||||
}
|
||||
|
||||
auto req_finished = CreateGetScoreNpIdRequest(builder, board_id, builder.CreateVector(davec), with_comment, with_gameinfo);
|
||||
|
||||
builder.Finish(req_finished);
|
||||
u8* buf = builder.GetBufferPointer();
|
||||
usz bufsize = builder.GetSize();
|
||||
data.resize(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
|
||||
|
||||
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
|
||||
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
|
||||
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
|
||||
|
||||
return forge_send(CommandType::GetScoreNpid, req_id, data);
|
||||
}
|
||||
|
||||
bool rpcn_client::get_score_friend(u32 req_id, const SceNpCommunicationId& communication_id, SceNpScoreBoardId board_id, bool with_comment, bool with_gameinfo)
|
||||
{
|
||||
std::vector<u8> data;
|
||||
flatbuffers::FlatBufferBuilder builder(1024);
|
||||
auto req_finished = CreateGetScoreFriendsRequest(builder, board_id, with_comment, with_gameinfo);
|
||||
builder.Finish(req_finished);
|
||||
|
||||
u8* buf = builder.GetBufferPointer();
|
||||
usz bufsize = builder.GetSize();
|
||||
data.resize(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
|
||||
|
||||
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
|
||||
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
|
||||
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
|
||||
|
||||
return forge_send(CommandType::GetScoreFriends, req_id, data);
|
||||
}
|
||||
|
||||
std::vector<u8> rpcn_client::forge_request(u16 command, u64 packet_id, const std::vector<u8>& data) const
|
||||
{
|
||||
u16 packet_size = data.size() + RPCN_HEADER_SIZE;
|
||||
u32 packet_size = data.size() + RPCN_HEADER_SIZE;
|
||||
|
||||
std::vector<u8> packet(packet_size);
|
||||
packet[0] = PacketType::Request;
|
||||
reinterpret_cast<le_t<u16>&>(packet[1]) = command;
|
||||
reinterpret_cast<le_t<u16>&>(packet[3]) = packet_size;
|
||||
reinterpret_cast<le_t<u64>&>(packet[5]) = packet_id;
|
||||
reinterpret_cast<le_t<u32>&>(packet[3]) = packet_size;
|
||||
reinterpret_cast<le_t<u64>&>(packet[7]) = packet_id;
|
||||
|
||||
memcpy(packet.data() + RPCN_HEADER_SIZE, data.data(), data.size());
|
||||
return packet;
|
||||
}
|
||||
|
||||
bool rpcn_client::is_error(ErrorType err) const
|
||||
{
|
||||
if (err >= ErrorType::__error_last)
|
||||
{
|
||||
rpcn_log.error("Invalid error returned!");
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (err)
|
||||
{
|
||||
case NoError: return false;
|
||||
case Malformed: rpcn_log.error("Sent packet was malformed!"); break;
|
||||
case Invalid: rpcn_log.error("Sent command was invalid!"); break;
|
||||
case InvalidInput: rpcn_log.error("Sent data was invalid!"); break;
|
||||
case TooSoon: rpcn_log.error("Request happened too soon!"); break;
|
||||
case LoginError: rpcn_log.error("Unknown login error!"); break;
|
||||
case LoginAlreadyLoggedIn: rpcn_log.error("User is already logged in!"); break;
|
||||
case LoginInvalidUsername: rpcn_log.error("Login error: invalid username!"); break;
|
||||
case LoginInvalidPassword: rpcn_log.error("Login error: invalid password!"); break;
|
||||
case LoginInvalidToken: rpcn_log.error("Login error: invalid token!"); break;
|
||||
case CreationError: rpcn_log.error("Error creating an account!"); break;
|
||||
case CreationExistingUsername: rpcn_log.error("Error creating an account: existing username!"); break;
|
||||
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!"); 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;
|
||||
case Blocked: rpcn_log.error("You're blocked!"); break;
|
||||
case AlreadyFriend: rpcn_log.error("You're already friends!"); break;
|
||||
case Unsupported: rpcn_log.error("An unsupported operation was attempted!"); break;
|
||||
default: rpcn_log.fatal("Unhandled ErrorType reached the switch?"); break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool rpcn_client::error_and_disconnect(const std::string& error_msg)
|
||||
{
|
||||
connected = false;
|
||||
@ -1760,6 +1900,7 @@ namespace rpcn
|
||||
{
|
||||
return state;
|
||||
}
|
||||
|
||||
want_auth = true;
|
||||
sem_rpcn.release();
|
||||
}
|
||||
|
@ -118,6 +118,8 @@ namespace rpcn
|
||||
Terminate,
|
||||
Create,
|
||||
SendToken,
|
||||
SendResetToken,
|
||||
ResetPassword,
|
||||
AddFriend,
|
||||
RemoveFriend,
|
||||
AddBlock,
|
||||
@ -138,6 +140,13 @@ namespace rpcn
|
||||
RequestSignalingInfos,
|
||||
RequestTicket,
|
||||
SendMessage,
|
||||
GetBoardInfos,
|
||||
RecordScore,
|
||||
StoreScoreData,
|
||||
GetScoreData,
|
||||
GetScoreRange,
|
||||
GetScoreFriends,
|
||||
GetScoreNpid,
|
||||
};
|
||||
|
||||
enum NotificationType : u16
|
||||
@ -204,6 +213,7 @@ namespace rpcn
|
||||
NotFound, // Object of the query was not found(room, user, etc)
|
||||
Blocked, // The operation can't complete because you've been blocked
|
||||
AlreadyFriend, // Can't add friend because already friend
|
||||
ScoreNotBest, // A better score is already registered for that user/character_id
|
||||
Unsupported,
|
||||
__error_last
|
||||
};
|
||||
@ -221,6 +231,7 @@ namespace rpcn
|
||||
|
||||
localized_string_id rpcn_state_to_localized_string_id(rpcn::rpcn_state state);
|
||||
std::string rpcn_state_to_string(rpcn::rpcn_state state);
|
||||
bool is_error(ErrorType err);
|
||||
|
||||
class rpcn_client
|
||||
{
|
||||
@ -290,7 +301,7 @@ namespace rpcn
|
||||
|
||||
public:
|
||||
~rpcn_client();
|
||||
rpcn_client(rpcn_client& other) = delete;
|
||||
rpcn_client(rpcn_client& other) = delete;
|
||||
void operator=(const rpcn_client&) = delete;
|
||||
static std::shared_ptr<rpcn_client> get_instance();
|
||||
rpcn_state wait_for_connection();
|
||||
@ -299,8 +310,10 @@ namespace rpcn
|
||||
void get_friends_and_register_cb(friend_data& friend_infos, friend_cb_func cb_func, void* cb_param);
|
||||
void remove_friend_cb(friend_cb_func, void* cb_param);
|
||||
|
||||
ErrorType create_user(const std::string& npid, const std::string& password, const std::string& online_name, const std::string& avatar_url, const std::string& email);
|
||||
ErrorType create_user(std::string_view npid, std::string_view password, std::string_view online_name, std::string_view avatar_url, std::string_view email);
|
||||
ErrorType resend_token(const std::string& npid, const std::string& password);
|
||||
ErrorType send_reset_token(std::string_view npid, std::string_view email);
|
||||
ErrorType reset_password(std::string_view npid, std::string_view token, std::string_view password);
|
||||
bool add_friend(const std::string& friend_username);
|
||||
bool remove_friend(const std::string& friend_username);
|
||||
|
||||
@ -350,6 +363,11 @@ namespace rpcn
|
||||
bool req_sign_infos(u32 req_id, const std::string& npid);
|
||||
bool req_ticket(u32 req_id, const std::string& service_id, const std::vector<u8>& cookie);
|
||||
bool sendmessage(const message_data& msg_data, const std::set<std::string>& npids);
|
||||
bool get_board_infos(u32 req_id, const SceNpCommunicationId& communication_id, SceNpScoreBoardId board_id);
|
||||
bool record_score(u32 req_id, const SceNpCommunicationId& communication_id, SceNpScoreBoardId board_id, SceNpScorePcId char_id, SceNpScoreValue score, const std::optional<std::string> comment, const std::optional<std::vector<u8>> score_data);
|
||||
bool get_score_range(u32 req_id, const SceNpCommunicationId& communication_id, SceNpScoreBoardId board_id, u32 start_rank, u32 num_rank, bool with_comment, bool with_gameinfo);
|
||||
bool get_score_npid(u32 req_id, const SceNpCommunicationId& communication_id, SceNpScoreBoardId board_id, const std::vector<std::pair<SceNpId, s32>>& npids, bool with_comment, bool with_gameinfo);
|
||||
bool get_score_friend(u32 req_id, const SceNpCommunicationId& communication_id, SceNpScoreBoardId board_id, bool with_comment, bool with_gameinfo);
|
||||
|
||||
const std::string& get_online_name() const
|
||||
{
|
||||
@ -368,6 +386,15 @@ namespace rpcn
|
||||
{
|
||||
return port_sig.load();
|
||||
}
|
||||
u32 get_addr_local() const
|
||||
{
|
||||
return local_addr_sig.load();
|
||||
}
|
||||
|
||||
void update_local_addr(u32 addr)
|
||||
{
|
||||
local_addr_sig = std::bit_cast<u32, be_t<u32>>(addr);
|
||||
}
|
||||
|
||||
private:
|
||||
bool get_reply(u64 expected_id, std::vector<u8>& data);
|
||||
@ -376,7 +403,6 @@ namespace rpcn
|
||||
bool forge_send(u16 command, u64 packet_id, const std::vector<u8>& data);
|
||||
bool forge_send_reply(u16 command, u64 packet_id, const std::vector<u8>& data, std::vector<u8>& reply_data);
|
||||
|
||||
bool is_error(ErrorType err) const;
|
||||
bool error_and_disconnect(const std::string& error_mgs);
|
||||
|
||||
std::string get_wolfssl_error(WOLFSSL* wssl, int error) const;
|
||||
@ -432,6 +458,7 @@ namespace rpcn
|
||||
|
||||
atomic_t<u32> addr_sig{};
|
||||
atomic_t<u16> port_sig{};
|
||||
atomic_t<u32> local_addr_sig{};
|
||||
};
|
||||
|
||||
} // namespace rpcn
|
||||
|
@ -21,6 +21,14 @@ void cfg_rpcn::load()
|
||||
rpcn_log.notice("RPCN config missing. Using default settings. Path: %s", path);
|
||||
from_default();
|
||||
}
|
||||
|
||||
// Update config from old version(s)
|
||||
if (version == 1)
|
||||
{
|
||||
password.from_string("");
|
||||
version.set(2);
|
||||
save();
|
||||
}
|
||||
}
|
||||
|
||||
void cfg_rpcn::save() const
|
||||
@ -55,7 +63,7 @@ std::string cfg_rpcn::generate_npid()
|
||||
std::string gen_npid = "RPCS3_";
|
||||
|
||||
const char list_chars[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
|
||||
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
|
||||
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
|
||||
|
||||
std::srand(time(nullptr));
|
||||
|
||||
@ -72,6 +80,32 @@ std::string cfg_rpcn::get_host() const
|
||||
return host.to_string();
|
||||
}
|
||||
|
||||
std::vector<std::pair<std::string, std::string>> cfg_rpcn::get_hosts()
|
||||
{
|
||||
std::vector<std::pair<std::string, std::string>> vec_hosts;
|
||||
auto hosts_list = fmt::split(hosts.to_string(), {"|||"});
|
||||
|
||||
for (const auto& cur_host : hosts_list)
|
||||
{
|
||||
auto desc_and_host = fmt::split(cur_host, {"|"});
|
||||
if (desc_and_host.size() != 2)
|
||||
{
|
||||
rpcn_log.error("Invalid host in the list of hosts: %s", cur_host);
|
||||
continue;
|
||||
}
|
||||
vec_hosts.push_back(std::make_pair(std::move(desc_and_host[0]), std::move(desc_and_host[1])));
|
||||
}
|
||||
|
||||
if (vec_hosts.empty())
|
||||
{
|
||||
hosts.from_default();
|
||||
save();
|
||||
return get_hosts();
|
||||
}
|
||||
|
||||
return vec_hosts;
|
||||
}
|
||||
|
||||
std::string cfg_rpcn::get_npid()
|
||||
{
|
||||
std::string final_npid = npid.to_string();
|
||||
@ -94,22 +128,80 @@ std::string cfg_rpcn::get_token() const
|
||||
return token.to_string();
|
||||
}
|
||||
|
||||
void cfg_rpcn::set_host(const std::string& host)
|
||||
void cfg_rpcn::set_host(std::string_view host)
|
||||
{
|
||||
this->host.from_string(host);
|
||||
}
|
||||
|
||||
void cfg_rpcn::set_npid(const std::string& npid)
|
||||
void cfg_rpcn::set_npid(std::string_view npid)
|
||||
{
|
||||
this->npid.from_string(npid);
|
||||
}
|
||||
|
||||
void cfg_rpcn::set_password(const std::string& password)
|
||||
void cfg_rpcn::set_password(std::string_view password)
|
||||
{
|
||||
this->password.from_string(password);
|
||||
}
|
||||
|
||||
void cfg_rpcn::set_token(const std::string& token)
|
||||
void cfg_rpcn::set_token(std::string_view token)
|
||||
{
|
||||
this->token.from_string(token);
|
||||
}
|
||||
|
||||
void cfg_rpcn::set_hosts(const std::vector<std::pair<std::string, std::string>>& vec_hosts)
|
||||
{
|
||||
std::string final_string;
|
||||
for (const auto& [cur_desc, cur_host] : vec_hosts)
|
||||
{
|
||||
fmt::append(final_string, "%s|%s|||", cur_desc, cur_host);
|
||||
}
|
||||
|
||||
if (final_string.empty())
|
||||
{
|
||||
hosts.from_default();
|
||||
return;
|
||||
}
|
||||
|
||||
final_string.resize(final_string.size() - 3);
|
||||
hosts.from_string(final_string);
|
||||
}
|
||||
|
||||
bool cfg_rpcn::add_host(std::string_view new_description, std::string_view new_host)
|
||||
{
|
||||
auto cur_hosts = get_hosts();
|
||||
|
||||
for (const auto& [cur_desc, cur_host] : cur_hosts)
|
||||
{
|
||||
if (cur_desc == new_description && cur_host == new_host)
|
||||
return false;
|
||||
}
|
||||
|
||||
cur_hosts.push_back(std::make_pair(std::string(new_description), std::string(new_host)));
|
||||
set_hosts(cur_hosts);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cfg_rpcn::del_host(std::string_view del_description, std::string_view del_host)
|
||||
{
|
||||
// Do not delete default servers
|
||||
if ((del_description == "Official RPCN Server" && del_host == "np.rpcs3.net") ||
|
||||
(del_description == "RPCN Test Server" && del_host == "test-np.rpcs3.net"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
auto cur_hosts = get_hosts();
|
||||
|
||||
for (auto it = cur_hosts.begin(); it != cur_hosts.end(); it++)
|
||||
{
|
||||
if (it->first == del_description && it->second == del_host)
|
||||
{
|
||||
cur_hosts.erase(it);
|
||||
set_hosts(cur_hosts);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -4,10 +4,12 @@
|
||||
|
||||
struct cfg_rpcn : cfg::node
|
||||
{
|
||||
cfg::uint32 version{this, "Version", 1};
|
||||
cfg::string host{this, "Host", "np.rpcs3.net"};
|
||||
cfg::string npid{this, "NPID", ""};
|
||||
cfg::string password{this, "Password", ""};
|
||||
cfg::string token{this, "Token", ""};
|
||||
cfg::string hosts{this, "Hosts", "Official RPCN Server|np.rpcs3.net|||RPCN Test Server|test-np.rpcs3.net"};
|
||||
|
||||
void load();
|
||||
void save() const;
|
||||
@ -16,15 +18,19 @@ struct cfg_rpcn : cfg::node
|
||||
std::string get_npid(); // not const because it can save if npid is requested and it has never been set
|
||||
std::string get_password() const;
|
||||
std::string get_token() const;
|
||||
std::vector<std::pair<std::string, std::string>> get_hosts(); // saves default if no valid server in the list
|
||||
|
||||
void set_host(const std::string& host);
|
||||
void set_npid(const std::string& npid);
|
||||
void set_password(const std::string& password);
|
||||
void set_token(const std::string& token);
|
||||
void set_host(std::string_view host);
|
||||
void set_npid(std::string_view npid);
|
||||
void set_password(std::string_view password);
|
||||
void set_token(std::string_view token);
|
||||
bool add_host(std::string_view description, std::string_view host);
|
||||
bool del_host(std::string_view description, std::string_view host);
|
||||
|
||||
private:
|
||||
private:
|
||||
static std::string get_path();
|
||||
static std::string generate_npid();
|
||||
void set_hosts(const std::vector<std::pair<std::string, std::string>>& vec_hosts);
|
||||
};
|
||||
|
||||
extern cfg_rpcn g_cfg_rpcn;
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Emu/Cell/Modules/cellSysutil.h"
|
||||
#include "np_handler.h"
|
||||
#include "Emu/NP/vport0.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
@ -15,28 +16,26 @@
|
||||
|
||||
LOG_CHANNEL(sign_log, "Signaling");
|
||||
|
||||
std::vector<std::pair<std::pair<u32, u16>, std::vector<u8>>> get_sign_msgs();
|
||||
s32 send_packet_from_p2p_port(const std::vector<u8>& data, const sockaddr_in& addr);
|
||||
void need_network();
|
||||
|
||||
template <>
|
||||
void fmt_class_string<SignalingCommand>::format(std::string& out, u64 arg)
|
||||
{
|
||||
format_enum(out, arg, [](auto value)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case signal_ping: return "PING";
|
||||
case signal_pong: return "PONG";
|
||||
case signal_connect: return "CONNECT";
|
||||
case signal_connect_ack: return "CONNECT_ACK";
|
||||
case signal_confirm: return "CONFIRM";
|
||||
case signal_finished: return "FINISHED";
|
||||
case signal_finished_ack: return "FINISHED_ACK";
|
||||
}
|
||||
switch (value)
|
||||
{
|
||||
case signal_ping: return "PING";
|
||||
case signal_pong: return "PONG";
|
||||
case signal_connect: return "CONNECT";
|
||||
case signal_connect_ack: return "CONNECT_ACK";
|
||||
case signal_confirm: return "CONFIRM";
|
||||
case signal_finished: return "FINISHED";
|
||||
case signal_finished_ack: return "FINISHED_ACK";
|
||||
}
|
||||
|
||||
return unknown;
|
||||
});
|
||||
return unknown;
|
||||
});
|
||||
}
|
||||
|
||||
signaling_handler::signaling_handler()
|
||||
@ -77,10 +76,10 @@ void signaling_handler::signal_sig_callback(u32 conn_id, int event)
|
||||
if (sig_cb)
|
||||
{
|
||||
sysutil_register_cb([sig_cb = this->sig_cb, sig_cb_ctx = this->sig_cb_ctx, conn_id, event, sig_cb_arg = this->sig_cb_arg](ppu_thread& cb_ppu) -> s32
|
||||
{
|
||||
sig_cb(cb_ppu, sig_cb_ctx, conn_id, event, 0, sig_cb_arg);
|
||||
return 0;
|
||||
});
|
||||
{
|
||||
sig_cb(cb_ppu, sig_cb_ctx, conn_id, event, 0, sig_cb_arg);
|
||||
return 0;
|
||||
});
|
||||
sign_log.notice("Called sig CB: 0x%x (conn_id: %d)", event, conn_id);
|
||||
}
|
||||
|
||||
@ -93,11 +92,11 @@ void signaling_handler::signal_ext_sig_callback(u32 conn_id, int event) const
|
||||
if (sig_ext_cb)
|
||||
{
|
||||
sysutil_register_cb([sig_ext_cb = this->sig_ext_cb, sig_ext_cb_ctx = this->sig_ext_cb_ctx, conn_id, event, sig_ext_cb_arg = this->sig_ext_cb_arg](ppu_thread& cb_ppu) -> s32
|
||||
{
|
||||
sig_ext_cb(cb_ppu, sig_ext_cb_ctx, conn_id, event, 0, sig_ext_cb_arg);
|
||||
return 0;
|
||||
});
|
||||
sign_log.notice("Called EXT sig CB: 0x%x (conn_id: %d, member_id: %d)", event, conn_id);
|
||||
{
|
||||
sig_ext_cb(cb_ppu, sig_ext_cb_ctx, conn_id, event, 0, sig_ext_cb_arg);
|
||||
return 0;
|
||||
});
|
||||
sign_log.notice("Called EXT sig CB: 0x%x (conn_id: %d)", event, conn_id);
|
||||
}
|
||||
}
|
||||
|
||||
@ -107,10 +106,10 @@ void signaling_handler::signal_sig2_callback(u64 room_id, u16 member_id, SceNpMa
|
||||
if (sig2_cb)
|
||||
{
|
||||
sysutil_register_cb([sig2_cb = this->sig2_cb, sig2_cb_ctx = this->sig2_cb_ctx, room_id, member_id, event, sig2_cb_arg = this->sig2_cb_arg](ppu_thread& cb_ppu) -> s32
|
||||
{
|
||||
sig2_cb(cb_ppu, sig2_cb_ctx, room_id, member_id, event, 0, sig2_cb_arg);
|
||||
return 0;
|
||||
});
|
||||
{
|
||||
sig2_cb(cb_ppu, sig2_cb_ctx, room_id, member_id, event, 0, sig2_cb_arg);
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
|
||||
sign_log.notice("Called sig2 CB: 0x%x (room_id: %d, member_id: %d)", event, room_id, member_id);
|
||||
@ -180,15 +179,15 @@ void signaling_handler::process_incoming_messages()
|
||||
|
||||
for (const auto& msg : msgs)
|
||||
{
|
||||
if (msg.second.size() != sizeof(signaling_packet))
|
||||
if (msg.data.size() != sizeof(signaling_packet))
|
||||
{
|
||||
sign_log.error("Received an invalid signaling packet");
|
||||
continue;
|
||||
}
|
||||
|
||||
auto op_addr = msg.first.first;
|
||||
auto op_port = msg.first.second;
|
||||
auto* sp = reinterpret_cast<const signaling_packet*>(msg.second.data());
|
||||
auto op_addr = msg.src_addr;
|
||||
auto op_port = msg.src_port;
|
||||
auto* sp = reinterpret_cast<const signaling_packet*>(msg.data.data());
|
||||
|
||||
if (!validate_signaling_packet(sp))
|
||||
continue;
|
||||
@ -231,8 +230,8 @@ void signaling_handler::process_incoming_messages()
|
||||
si = ::at32(sig1_peers, conn_id);
|
||||
// Activate the connection without triggering the main CB
|
||||
si->connStatus = SCE_NP_SIGNALING_CONN_STATUS_ACTIVE;
|
||||
si->addr = op_addr;
|
||||
si->port = op_port;
|
||||
si->addr = op_addr;
|
||||
si->port = op_port;
|
||||
si->ext_status = ext_sign_peer;
|
||||
// Notify extended callback that peer activated
|
||||
signal_ext_sig_callback(conn_id, SCE_NP_SIGNALING_EVENT_EXT_PEER_ACTIVATED);
|
||||
@ -259,30 +258,51 @@ void signaling_handler::process_incoming_messages()
|
||||
}
|
||||
}
|
||||
|
||||
sent_packet.command = signal_ping;
|
||||
sent_packet.command = signal_ping;
|
||||
sent_packet.timestamp = now.time_since_epoch().count();
|
||||
send_signaling_packet(sent_packet, si->addr, si->port);
|
||||
queue_signaling_packet(sent_packet, si, now + REPEAT_PING_DELAY);
|
||||
};
|
||||
|
||||
const auto update_rtt = [&]()
|
||||
{
|
||||
u32 rtt = now.time_since_epoch().count() - sp->timestamp;
|
||||
si->last_rtts[(si->rtt_counters % 6)] = rtt;
|
||||
si->rtt_counters++;
|
||||
|
||||
std::size_t num_rtts = std::min(static_cast<std::size_t>(6), si->rtt_counters);
|
||||
u64 sum = 0;
|
||||
for (std::size_t index = 0; index < num_rtts; index++)
|
||||
{
|
||||
sum += si->last_rtts[index];
|
||||
}
|
||||
|
||||
si->rtt = (sum / num_rtts) / 1000;
|
||||
};
|
||||
|
||||
switch (sp->command)
|
||||
{
|
||||
case signal_ping:
|
||||
reply = true;
|
||||
schedule_repeat = false;
|
||||
sent_packet.command = signal_pong;
|
||||
reply = true;
|
||||
schedule_repeat = false;
|
||||
sent_packet.command = signal_pong;
|
||||
sent_packet.timestamp = sp->timestamp;
|
||||
break;
|
||||
case signal_pong:
|
||||
update_rtt();
|
||||
reply = false;
|
||||
schedule_repeat = false;
|
||||
reschedule_packet(si, signal_ping, now + 15s);
|
||||
reschedule_packet(si, signal_ping, now + 10s);
|
||||
break;
|
||||
case signal_connect:
|
||||
reply = true;
|
||||
schedule_repeat = true;
|
||||
sent_packet.command = signal_connect_ack;
|
||||
reply = true;
|
||||
schedule_repeat = true;
|
||||
sent_packet.command = signal_connect_ack;
|
||||
sent_packet.timestamp = sp->timestamp;
|
||||
// connection is established
|
||||
// TODO: notify extended callback!
|
||||
break;
|
||||
case signal_connect_ack:
|
||||
update_rtt();
|
||||
reply = true;
|
||||
schedule_repeat = false;
|
||||
setup_ping();
|
||||
@ -357,6 +377,17 @@ void signaling_handler::operator()()
|
||||
break; // qpackets will be emptied of all packets from this user so we're requeuing
|
||||
}
|
||||
|
||||
// Update the timestamp if necessary
|
||||
switch (it->second.packet.command)
|
||||
{
|
||||
case signal_connect:
|
||||
case signal_ping:
|
||||
it->second.packet.timestamp = now.time_since_epoch().count();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Resend the packet
|
||||
send_signaling_packet(it->second.packet, it->second.sig_info->addr, it->second.sig_info->port);
|
||||
|
||||
@ -427,7 +458,7 @@ void signaling_handler::update_si_mapped_addr(std::shared_ptr<signaling_info>& s
|
||||
if (si->addr != new_addr || si->port != new_port)
|
||||
{
|
||||
in_addr addr_old, addr_new;
|
||||
addr_old.s_addr = si->addr;
|
||||
addr_old.s_addr = si->mapped_addr;
|
||||
addr_new.s_addr = new_addr;
|
||||
|
||||
char ip_str_old[16];
|
||||
@ -435,7 +466,7 @@ void signaling_handler::update_si_mapped_addr(std::shared_ptr<signaling_info>& s
|
||||
inet_ntop(AF_INET, &addr_old, ip_str_old, sizeof(ip_str_old));
|
||||
inet_ntop(AF_INET, &addr_new, ip_str_new, sizeof(ip_str_new));
|
||||
|
||||
sign_log.trace("Updated Mapped Address from %s:%d to %s:%d", ip_str_old, si->port, ip_str_new, new_port);
|
||||
sign_log.trace("Updated Mapped Address from %s:%d to %s:%d", ip_str_old, si->mapped_port, ip_str_new, new_port);
|
||||
si->mapped_addr = new_addr;
|
||||
si->mapped_port = new_port;
|
||||
}
|
||||
@ -493,9 +524,12 @@ void signaling_handler::set_self_sig2_info(u64 room_id, u16 member_id)
|
||||
|
||||
void signaling_handler::send_signaling_packet(signaling_packet& sp, u32 addr, u16 port) const
|
||||
{
|
||||
std::vector<u8> packet(sizeof(signaling_packet) + sizeof(u16));
|
||||
reinterpret_cast<le_t<u16>&>(packet[0]) = 65535;
|
||||
memcpy(packet.data() + sizeof(u16), &sp, sizeof(signaling_packet));
|
||||
std::vector<u8> packet(sizeof(signaling_packet) + VPORT_0_HEADER_SIZE);
|
||||
reinterpret_cast<le_t<u16>&>(packet[0]) = 0; // VPort 0
|
||||
packet[2] = SUBSET_SIGNALING;
|
||||
sp.sent_addr = addr;
|
||||
sp.sent_port = port;
|
||||
memcpy(packet.data() + VPORT_0_HEADER_SIZE, &sp, sizeof(signaling_packet));
|
||||
|
||||
sockaddr_in dest;
|
||||
memset(&dest, 0, sizeof(sockaddr_in));
|
||||
@ -508,9 +542,6 @@ void signaling_handler::send_signaling_packet(signaling_packet& sp, u32 addr, u1
|
||||
|
||||
sign_log.trace("Sending %s packet to %s:%d", sp.command, ip_str, port);
|
||||
|
||||
sp.sent_addr = addr;
|
||||
sp.sent_port = port;
|
||||
|
||||
if (send_packet_from_p2p_port(packet, dest) == -1)
|
||||
{
|
||||
sign_log.error("Failed to send signaling packet to %s:%d", ip_str, port);
|
||||
@ -534,7 +565,7 @@ std::shared_ptr<signaling_info> signaling_handler::get_signaling_ptr(const signa
|
||||
memcpy(npid_buf, sp->V1.npid.handle.data, 16);
|
||||
std::string npid(npid_buf);
|
||||
|
||||
if (!npid_to_conn_id.count(npid))
|
||||
if (!npid_to_conn_id.contains(npid))
|
||||
return nullptr;
|
||||
|
||||
const u32 conn_id = ::at32(npid_to_conn_id, npid);
|
||||
@ -566,6 +597,7 @@ void signaling_handler::start_sig_nl(u32 conn_id, u32 addr, u16 port)
|
||||
{
|
||||
auto& sent_packet = sig1_packet;
|
||||
sent_packet.command = signal_connect;
|
||||
sent_packet.timestamp = steady_clock::now().time_since_epoch().count();
|
||||
|
||||
ensure(sig1_peers.contains(conn_id));
|
||||
std::shared_ptr<signaling_info> si = ::at32(sig1_peers, conn_id);
|
||||
@ -578,12 +610,29 @@ void signaling_handler::start_sig_nl(u32 conn_id, u32 addr, u16 port)
|
||||
wake_up();
|
||||
}
|
||||
|
||||
void signaling_handler::stop_sig(u32 conn_id)
|
||||
{
|
||||
std::lock_guard lock(data_mutex);
|
||||
|
||||
if (!sig1_peers.contains(conn_id))
|
||||
return;
|
||||
|
||||
auto& sent_packet = sig1_packet;
|
||||
sent_packet.command = signal_finished;
|
||||
|
||||
std::shared_ptr<signaling_info> si = ::at32(sig1_peers, conn_id);
|
||||
|
||||
send_signaling_packet(sent_packet, si->addr, si->port);
|
||||
queue_signaling_packet(sent_packet, si, steady_clock::now() + REPEAT_FINISHED_DELAY);
|
||||
}
|
||||
|
||||
void signaling_handler::start_sig2(u64 room_id, u16 member_id)
|
||||
{
|
||||
std::lock_guard lock(data_mutex);
|
||||
|
||||
auto& sent_packet = sig2_packet;
|
||||
sent_packet.command = signal_connect;
|
||||
sent_packet.timestamp = steady_clock::now().time_since_epoch().count();
|
||||
|
||||
ensure(sig2_peers.contains(room_id));
|
||||
const auto& sp = ::at32(sig2_peers, room_id);
|
||||
@ -633,6 +682,7 @@ u32 signaling_handler::create_sig_infos(const SceNpId* npid)
|
||||
sig1_peers.emplace(conn_id, std::make_shared<signaling_info>());
|
||||
::at32(sig1_peers, conn_id)->version = 1;
|
||||
::at32(sig1_peers, conn_id)->conn_id = conn_id;
|
||||
::at32(sig1_peers, conn_id)->npid = *npid;
|
||||
|
||||
return conn_id;
|
||||
}
|
||||
@ -671,10 +721,33 @@ u32 signaling_handler::init_sig_infos(const SceNpId* npid)
|
||||
|
||||
signaling_info signaling_handler::get_sig_infos(u32 conn_id)
|
||||
{
|
||||
std::lock_guard lock(data_mutex);
|
||||
return *sig1_peers[conn_id];
|
||||
}
|
||||
|
||||
void signaling_handler::set_sig2_infos(u64 room_id, u16 member_id, s32 status, u32 addr, u16 port, bool self)
|
||||
std::optional<u32> signaling_handler::get_conn_id_from_npid(const SceNpId* npid)
|
||||
{
|
||||
std::lock_guard lock(data_mutex);
|
||||
// Diff behaviour here depending on SDK version, 420+ always succeeds
|
||||
return create_sig_infos(npid);
|
||||
}
|
||||
|
||||
std::optional<u32> signaling_handler::get_conn_id_from_addr(u32 addr, u16 port)
|
||||
{
|
||||
std::lock_guard lock(data_mutex);
|
||||
|
||||
for (const auto& [conn_id, conn_info] : sig1_peers)
|
||||
{
|
||||
if (conn_info && std::bit_cast<u32, be_t<u32>>(conn_info->addr) == addr && conn_info->port == port)
|
||||
{
|
||||
return conn_id;
|
||||
}
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
void signaling_handler::set_sig2_infos(u64 room_id, u16 member_id, s32 status, u32 addr, u16 port, const SceNpId& npid, bool self)
|
||||
{
|
||||
std::lock_guard lock(data_mutex);
|
||||
if (!sig2_peers[room_id][member_id])
|
||||
@ -688,6 +761,7 @@ void signaling_handler::set_sig2_infos(u64 room_id, u16 member_id, s32 status, u
|
||||
peer->version = 2;
|
||||
peer->room_id = room_id;
|
||||
peer->member_id = member_id;
|
||||
peer->npid = npid;
|
||||
}
|
||||
|
||||
signaling_info signaling_handler::get_sig2_infos(u64 room_id, u16 member_id)
|
||||
@ -697,10 +771,10 @@ signaling_info signaling_handler::get_sig2_infos(u64 room_id, u16 member_id)
|
||||
if (!sig2_peers[room_id][member_id])
|
||||
{
|
||||
sig2_peers[room_id][member_id] = std::make_shared<signaling_info>();
|
||||
auto& peer = sig2_peers[room_id][member_id];
|
||||
peer->room_id = room_id;
|
||||
peer->member_id = member_id;
|
||||
peer->version = 2;
|
||||
auto& peer = sig2_peers[room_id][member_id];
|
||||
peer->room_id = room_id;
|
||||
peer->member_id = member_id;
|
||||
peer->version = 2;
|
||||
}
|
||||
|
||||
return *sig2_peers[room_id][member_id];
|
||||
|
@ -7,11 +7,12 @@
|
||||
#include <unordered_map>
|
||||
#include <condition_variable>
|
||||
#include <chrono>
|
||||
#include <optional>
|
||||
|
||||
enum ext_signaling_status : u8
|
||||
{
|
||||
ext_sign_none = 0,
|
||||
ext_sign_peer = 1,
|
||||
ext_sign_none = 0,
|
||||
ext_sign_peer = 1,
|
||||
ext_sign_mutual = 2,
|
||||
};
|
||||
|
||||
@ -27,15 +28,24 @@ struct signaling_info
|
||||
|
||||
// For handler
|
||||
steady_clock::time_point time_last_msg_recvd = steady_clock::now();
|
||||
|
||||
bool self = false;
|
||||
u32 version = 0;
|
||||
SceNpId npid{};
|
||||
|
||||
// Signaling
|
||||
u32 conn_id = 0;
|
||||
ext_signaling_status ext_status = ext_sign_none;
|
||||
|
||||
// Matching2
|
||||
u64 room_id = 0;
|
||||
u16 member_id = 0;
|
||||
|
||||
// Stats
|
||||
u64 last_rtts[6] = {};
|
||||
std::size_t rtt_counters = 0;
|
||||
u32 rtt = 0;
|
||||
u32 pings_sent = 1, lost_pings = 0;
|
||||
u32 packet_loss = 0;
|
||||
};
|
||||
|
||||
enum SignalingCommand : u32
|
||||
@ -62,8 +72,10 @@ public:
|
||||
|
||||
u32 init_sig_infos(const SceNpId* npid);
|
||||
signaling_info get_sig_infos(u32 conn_id);
|
||||
std::optional<u32> get_conn_id_from_npid(const SceNpId* npid);
|
||||
std::optional<u32> get_conn_id_from_addr(u32 addr, u16 port);
|
||||
|
||||
void set_sig2_infos(u64 room_id, u16 member_id, s32 status, u32 addr, u16 port, bool self = false);
|
||||
void set_sig2_infos(u64 room_id, u16 member_id, s32 status, u32 addr, u16 port, const SceNpId& npid, bool self = false);
|
||||
signaling_info get_sig2_infos(u64 room_id, u16 member_id);
|
||||
|
||||
void set_sig_cb(u32 sig_cb_ctx, vm::ptr<SceNpSignalingHandler> sig_cb, vm::ptr<void> sig_cb_arg);
|
||||
@ -71,6 +83,7 @@ public:
|
||||
void set_sig2_cb(u16 sig2_cb_ctx, vm::ptr<SceNpMatching2SignalingCallback> sig2_cb, vm::ptr<void> sig2_cb_arg);
|
||||
|
||||
void start_sig(u32 conn_id, u32 addr, u16 port);
|
||||
void stop_sig(u32 conn_id);
|
||||
|
||||
void start_sig2(u64 room_id, u16 member_id);
|
||||
void disconnect_sig2_users(u64 room_id);
|
||||
@ -78,19 +91,21 @@ public:
|
||||
static constexpr auto thread_name = "Signaling Manager Thread"sv;
|
||||
|
||||
private:
|
||||
static constexpr auto REPEAT_CONNECT_DELAY = std::chrono::milliseconds(200);
|
||||
static constexpr auto REPEAT_PING_DELAY = std::chrono::milliseconds(500);
|
||||
static constexpr auto REPEAT_FINISHED_DELAY = std::chrono::milliseconds(500);
|
||||
static constexpr auto REPEAT_CONNECT_DELAY = std::chrono::milliseconds(200);
|
||||
static constexpr auto REPEAT_PING_DELAY = std::chrono::milliseconds(500);
|
||||
static constexpr auto REPEAT_FINISHED_DELAY = std::chrono::milliseconds(500);
|
||||
static constexpr be_t<u32> SIGNALING_SIGNATURE = (static_cast<u32>('S') << 24 | static_cast<u32>('I') << 16 | static_cast<u32>('G') << 8 | static_cast<u32>('N'));
|
||||
|
||||
struct signaling_packet
|
||||
{
|
||||
be_t<u32> signature = SIGNALING_SIGNATURE;
|
||||
le_t<u32> version;
|
||||
le_t<u64> timestamp;
|
||||
le_t<SignalingCommand> command;
|
||||
le_t<u32> sent_addr;
|
||||
le_t<u16> sent_port;
|
||||
union {
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
SceNpId npid;
|
||||
|
26
rpcs3/Emu/NP/vport0.h
Normal file
26
rpcs3/Emu/NP/vport0.h
Normal file
@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#else
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
#include "Emu/Cell/lv2/sys_net/nt_p2p_port.h"
|
||||
|
||||
s32 send_packet_from_p2p_port(const std::vector<u8>& data, const sockaddr_in& addr);
|
||||
std::vector<signaling_message> get_sign_msgs();
|
||||
std::vector<std::vector<u8>> get_rpcn_msgs();
|
||||
|
||||
constexpr s32 VPORT_0_HEADER_SIZE = sizeof(u16) + sizeof(u8);
|
||||
|
||||
// VPort 0 is invalid for sys_net so we use it for:
|
||||
// Subset 0: Messages from RPCN server, IP retrieval / UDP hole punching
|
||||
// Subset 1: Signaling
|
||||
enum VPORT_0_SUBSET : u8
|
||||
{
|
||||
SUBSET_RPCN = 0,
|
||||
SUBSET_SIGNALING = 1,
|
||||
};
|
@ -504,6 +504,7 @@
|
||||
<ClInclude Include="Emu\NP\generated\np2_structs_generated.h" />
|
||||
<ClInclude Include="Emu\NP\np_handler.h" />
|
||||
<ClInclude Include="Emu\NP\signaling_handler.h" />
|
||||
<ClInclude Include="Emu\NP\vport0.h" />
|
||||
<ClInclude Include="Emu\NP\np_allocator.h" />
|
||||
<ClInclude Include="Emu\NP\np_cache.h" />
|
||||
<ClInclude Include="Emu\NP\np_dnshook.h" />
|
||||
|
@ -1923,6 +1923,9 @@
|
||||
<ClInclude Include="Emu\NP\signaling_handler.h">
|
||||
<Filter>Emu\NP</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\NP\vport0.h">
|
||||
<Filter>Emu\NP</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\RSX\Overlays\overlay_osk_panel.h">
|
||||
<Filter>Emu\GPU\RSX\Overlays</Filter>
|
||||
</ClInclude>
|
||||
|
@ -6,11 +6,13 @@
|
||||
#include <QInputDialog>
|
||||
#include <QGroupBox>
|
||||
#include <QMenu>
|
||||
#include <QDialogButtonBox>
|
||||
#include <thread>
|
||||
|
||||
#include "qt_utils.h"
|
||||
|
||||
#include "rpcn_settings_dialog.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/NP/rpcn_config.h"
|
||||
|
||||
#include <wolfssl/ssl.h>
|
||||
@ -18,13 +20,50 @@
|
||||
|
||||
LOG_CHANNEL(rpcn_settings_log, "rpcn settings dlg");
|
||||
|
||||
bool validate_rpcn_username(const std::string& input)
|
||||
bool validate_rpcn_username(std::string_view username)
|
||||
{
|
||||
if (input.length() < 3 || input.length() > 16)
|
||||
if (username.length() < 3 || username.length() > 16)
|
||||
return false;
|
||||
|
||||
return std::all_of(input.cbegin(), input.cend(), [](const char c)
|
||||
{ return std::isalnum(c) || c == '-' || c == '_'; });
|
||||
return std::all_of(username.cbegin(), username.cend(), [](const char c)
|
||||
{
|
||||
return std::isalnum(static_cast<unsigned char>(c)) || c == '-' || c == '_';
|
||||
});
|
||||
}
|
||||
|
||||
bool validate_email(std::string_view email)
|
||||
{
|
||||
const QRegularExpressionValidator simple_email_validator(QRegularExpression("^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*$"));
|
||||
QString qstr_email = QString::fromStdString(std::string(email));
|
||||
int pos = 0;
|
||||
|
||||
if (qstr_email.isEmpty() || qstr_email.contains(' ') || qstr_email.contains('\t') || simple_email_validator.validate(qstr_email, pos) != QValidator::Acceptable)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool validate_token(std::string_view token)
|
||||
{
|
||||
return token.size() == 16 && std::all_of(token.cbegin(), token.cend(), [](const char c) { return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z'); });
|
||||
}
|
||||
|
||||
std::string derive_password(std::string_view user_password)
|
||||
{
|
||||
std::string_view salt_str = "No matter where you go, everybody's connected.";
|
||||
|
||||
u8 derived_password_digest[SHA3_256_DIGEST_LENGTH];
|
||||
ensure(!wc_PBKDF2(derived_password_digest, reinterpret_cast<const u8*>(user_password.data()), user_password.size(), reinterpret_cast<const u8*>(salt_str.data()), salt_str.size(), 200'000, SHA3_256_DIGEST_LENGTH, WC_SHA3_256));
|
||||
|
||||
std::string derived_password("0000000000000000000000000000000000000000000000000000000000000000");
|
||||
for (u32 i = 0; i < SHA3_256_DIGEST_LENGTH; i++)
|
||||
{
|
||||
constexpr auto pal = "0123456789ABCDEF";
|
||||
derived_password[i * 2] = pal[derived_password_digest[i] >> 4];
|
||||
derived_password[(i * 2) + 1] = pal[derived_password_digest[i] & 15];
|
||||
}
|
||||
|
||||
return derived_password;
|
||||
}
|
||||
|
||||
rpcn_settings_dialog::rpcn_settings_dialog(QWidget* parent)
|
||||
@ -51,6 +90,11 @@ rpcn_settings_dialog::rpcn_settings_dialog(QWidget* parent)
|
||||
|
||||
connect(btn_account, &QPushButton::clicked, this, [this]()
|
||||
{
|
||||
if (!Emu.IsStopped())
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error: Emulation Running"), tr("You need to stop the emulator before editing RPCN account information!"), QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
rpcn_account_dialog dlg(this);
|
||||
dlg.exec();
|
||||
});
|
||||
@ -66,8 +110,509 @@ rpcn_settings_dialog::rpcn_settings_dialog(QWidget* parent)
|
||||
rpcn_account_dialog::rpcn_account_dialog(QWidget* parent)
|
||||
: QDialog(parent)
|
||||
{
|
||||
setWindowTitle(tr("RPCN: Configuration"));
|
||||
setWindowTitle(tr("RPCN: Account"));
|
||||
setObjectName("rpcn_account_dialog");
|
||||
|
||||
QVBoxLayout* vbox_global = new QVBoxLayout();
|
||||
|
||||
QGroupBox* grp_server = new QGroupBox(tr("Server:"));
|
||||
QVBoxLayout* vbox_server = new QVBoxLayout();
|
||||
|
||||
QHBoxLayout* hbox_lbl_combo = new QHBoxLayout();
|
||||
QLabel* lbl_server = new QLabel(tr("Server:"));
|
||||
cbx_servers = new QComboBox();
|
||||
|
||||
refresh_combobox();
|
||||
|
||||
hbox_lbl_combo->addWidget(lbl_server);
|
||||
hbox_lbl_combo->addWidget(cbx_servers);
|
||||
|
||||
QHBoxLayout* hbox_buttons = new QHBoxLayout();
|
||||
QPushButton* btn_add_server = new QPushButton(tr("Add"));
|
||||
QPushButton* btn_del_server = new QPushButton(tr("Del"));
|
||||
hbox_buttons->addStretch();
|
||||
hbox_buttons->addWidget(btn_add_server);
|
||||
hbox_buttons->addWidget(btn_del_server);
|
||||
|
||||
vbox_server->addLayout(hbox_lbl_combo);
|
||||
vbox_server->addLayout(hbox_buttons);
|
||||
|
||||
grp_server->setLayout(vbox_server);
|
||||
vbox_global->addWidget(grp_server);
|
||||
|
||||
QGroupBox* grp_buttons = new QGroupBox();
|
||||
QVBoxLayout* vbox_buttons = new QVBoxLayout();
|
||||
QPushButton* btn_create = new QPushButton(tr("Create Account"));
|
||||
QPushButton* btn_edit = new QPushButton(tr("Edit Account"));
|
||||
QPushButton* btn_test = new QPushButton(tr("Test Account"));
|
||||
|
||||
vbox_buttons->addSpacing(10);
|
||||
vbox_buttons->addWidget(btn_create);
|
||||
vbox_buttons->addSpacing(10);
|
||||
vbox_buttons->addWidget(btn_edit);
|
||||
vbox_buttons->addSpacing(10);
|
||||
vbox_buttons->addWidget(btn_test);
|
||||
vbox_buttons->addSpacing(10);
|
||||
grp_buttons->setLayout(vbox_buttons);
|
||||
|
||||
vbox_global->addWidget(grp_buttons);
|
||||
|
||||
setLayout(vbox_global);
|
||||
|
||||
connect(cbx_servers, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [this](int index)
|
||||
{
|
||||
if (index < 0)
|
||||
return;
|
||||
|
||||
QVariant host = cbx_servers->itemData(index);
|
||||
|
||||
if (!host.isValid() || !host.canConvert<QString>())
|
||||
return;
|
||||
|
||||
g_cfg_rpcn.set_host(host.toString().toStdString());
|
||||
g_cfg_rpcn.save();
|
||||
});
|
||||
|
||||
connect(btn_add_server, &QAbstractButton::clicked, this, [this]()
|
||||
{
|
||||
rpcn_add_server_dialog dlg(this);
|
||||
dlg.exec();
|
||||
const auto new_server = dlg.get_new_server();
|
||||
if (new_server)
|
||||
{
|
||||
if (!g_cfg_rpcn.add_host(new_server->first, new_server->second))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Existing Server"), tr("You already have a server with this description & hostname in the list."), QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
g_cfg_rpcn.save();
|
||||
refresh_combobox();
|
||||
}
|
||||
});
|
||||
|
||||
connect(btn_del_server, &QAbstractButton::clicked, this, [this]()
|
||||
{
|
||||
const int index = cbx_servers->currentIndex();
|
||||
|
||||
if (index < 0)
|
||||
return;
|
||||
|
||||
const auto desc = cbx_servers->itemText(index).toStdString();
|
||||
const auto host = cbx_servers->itemData(index).toString().toStdString();
|
||||
|
||||
ensure(g_cfg_rpcn.del_host(desc, host));
|
||||
g_cfg_rpcn.save();
|
||||
refresh_combobox();
|
||||
});
|
||||
|
||||
connect(btn_create, &QAbstractButton::clicked, this, [this]()
|
||||
{
|
||||
rpcn_ask_username_dialog dlg_username(this, tr("Please enter your username.\n\n"
|
||||
"Note that these restrictions apply:\n"
|
||||
"- Username must be between 3 and 16 characters\n"
|
||||
"- Username can only contain a-z A-Z 0-9 '-' '_'\n"
|
||||
"- Username is case sensitive\n"));
|
||||
dlg_username.exec();
|
||||
auto username = dlg_username.get_username();
|
||||
|
||||
if (!username)
|
||||
return;
|
||||
|
||||
rpcn_ask_password_dialog dlg_password(this, tr("Please choose your password:\n\n"));
|
||||
dlg_password.exec();
|
||||
auto password = dlg_password.get_password();
|
||||
|
||||
if (!password)
|
||||
return;
|
||||
|
||||
rpcn_ask_email_dialog dlg_email(this, tr("An email address is required, please note:\n"
|
||||
"- A valid email is needed to receive the token that validates your account.\n"
|
||||
"- Your email won't be used for anything beyond sending you this token or the password reset token.\n\n"));
|
||||
dlg_email.exec();
|
||||
auto email = dlg_email.get_email();
|
||||
|
||||
if (!email)
|
||||
return;
|
||||
|
||||
if (QMessageBox::question(this, tr("RPCN: Account Creation"), tr("You are about to create an account with:\n-Username:%0\n-Email:%1\n\nIs this correct?").arg(QString::fromStdString(*username)).arg(QString::fromStdString(*email))) != QMessageBox::Yes)
|
||||
return;
|
||||
|
||||
{
|
||||
const auto rpcn = rpcn::rpcn_client::get_instance();
|
||||
const auto avatar_url = "https://rpcs3.net/cdn/netplay/DefaultAvatar.png";
|
||||
|
||||
if (auto result = rpcn->wait_for_connection(); result != rpcn::rpcn_state::failure_no_failure)
|
||||
{
|
||||
const QString error_message = tr("Failed to connect to RPCN server:\n%0").arg(QString::fromStdString(rpcn::rpcn_state_to_string(result)));
|
||||
QMessageBox::critical(this, tr("Error Connecting"), error_message, QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
if (auto error = rpcn->create_user(*username, *password, *username, avatar_url, *email); error != rpcn::ErrorType::NoError)
|
||||
{
|
||||
QString error_message;
|
||||
switch (error)
|
||||
{
|
||||
case rpcn::ErrorType::CreationExistingUsername: error_message = tr("An account with that username already exists!"); break;
|
||||
case rpcn::ErrorType::CreationBannedEmailProvider: error_message = tr("This email provider is banned!"); break;
|
||||
case rpcn::ErrorType::CreationExistingEmail: error_message = tr("An account with that email already exists!"); break;
|
||||
case rpcn::ErrorType::CreationError: error_message = tr("Unknown creation error"); break;
|
||||
default: error_message = tr("Unknown error"); break;
|
||||
}
|
||||
QMessageBox::critical(this, tr("Error Creating Account"), tr("Failed to create the account:\n%0").arg(error_message), QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
g_cfg_rpcn.set_npid(*username);
|
||||
g_cfg_rpcn.set_password(*password);
|
||||
g_cfg_rpcn.save();
|
||||
|
||||
rpcn_ask_token_dialog token_dlg(this, tr("Your account has been created successfully!\n"
|
||||
"Your account authentification was saved.\n"
|
||||
"Now all you need is to enter the token that was sent to your email.\n"
|
||||
"You can skip this step by leaving it empty and entering it later in the Edit Account section too.\n"));
|
||||
token_dlg.exec();
|
||||
auto token = token_dlg.get_token();
|
||||
|
||||
if (!token)
|
||||
return;
|
||||
|
||||
g_cfg_rpcn.set_token(*token);
|
||||
g_cfg_rpcn.save();
|
||||
});
|
||||
|
||||
connect(btn_edit, &QAbstractButton::clicked, this, [this]()
|
||||
{
|
||||
rpcn_account_edit_dialog dlg_edit(this);
|
||||
dlg_edit.exec();
|
||||
});
|
||||
|
||||
connect(btn_test, &QAbstractButton::clicked, this, [this]()
|
||||
{
|
||||
auto rpcn = rpcn::rpcn_client::get_instance();
|
||||
|
||||
if (auto res = rpcn->wait_for_connection(); res != rpcn::rpcn_state::failure_no_failure)
|
||||
{
|
||||
const QString error_msg = tr("Failed to connect to RPCN:\n%0").arg(QString::fromStdString(rpcn::rpcn_state_to_string(res)));
|
||||
QMessageBox::warning(this, tr("Error connecting to RPCN!"), error_msg, QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
if (auto res = rpcn->wait_for_authentified(); res != rpcn::rpcn_state::failure_no_failure)
|
||||
{
|
||||
const QString error_msg = tr("Failed to authentify to RPCN:\n%0").arg(QString::fromStdString(rpcn::rpcn_state_to_string(res)));
|
||||
QMessageBox::warning(this, tr("Error authentifying to RPCN!"), error_msg, QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
QMessageBox::information(this, tr("RPCN Account Valid!"), tr("Your account is valid!"), QMessageBox::Ok);
|
||||
});
|
||||
}
|
||||
|
||||
void rpcn_account_dialog::refresh_combobox()
|
||||
{
|
||||
g_cfg_rpcn.load();
|
||||
const auto vec_hosts = g_cfg_rpcn.get_hosts();
|
||||
auto cur_host = g_cfg_rpcn.get_host();
|
||||
int i = 0, index = 0;
|
||||
|
||||
cbx_servers->clear();
|
||||
|
||||
for (const auto& [desc, host] : vec_hosts)
|
||||
{
|
||||
cbx_servers->addItem(QString::fromStdString(desc), QString::fromStdString(host));
|
||||
if (cur_host == host)
|
||||
index = i;
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
cbx_servers->setCurrentIndex(index);
|
||||
}
|
||||
|
||||
rpcn_add_server_dialog::rpcn_add_server_dialog(QWidget* parent)
|
||||
: QDialog(parent)
|
||||
{
|
||||
setWindowTitle(tr("RPCN: Add Server"));
|
||||
setObjectName("rpcn_add_server_dialog");
|
||||
setMinimumSize(QSize(400, 200));
|
||||
|
||||
QVBoxLayout* vbox_global = new QVBoxLayout();
|
||||
|
||||
QLabel* lbl_description = new QLabel(tr("Description:"));
|
||||
QLineEdit* edt_description = new QLineEdit();
|
||||
QLabel* lbl_host = new QLabel(tr("Host:"));
|
||||
QLineEdit* edt_host = new QLineEdit();
|
||||
QDialogButtonBox* btn_box = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
|
||||
vbox_global->addWidget(lbl_description);
|
||||
vbox_global->addWidget(edt_description);
|
||||
vbox_global->addWidget(lbl_host);
|
||||
vbox_global->addWidget(edt_host);
|
||||
vbox_global->addWidget(btn_box);
|
||||
|
||||
setLayout(vbox_global);
|
||||
|
||||
connect(btn_box, &QDialogButtonBox::accepted, this, [this, edt_description, edt_host]()
|
||||
{
|
||||
auto description = edt_description->text();
|
||||
auto host = edt_host->text();
|
||||
|
||||
if (description.isEmpty())
|
||||
{
|
||||
QMessageBox::critical(this, tr("Missing Description"), tr("You must enter a description!"), QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
if (host.isEmpty())
|
||||
{
|
||||
QMessageBox::critical(this, tr("Missing Hostname"), tr("You must enter a hostname for the server!"), QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
m_new_server = std::make_pair(description.toStdString(), host.toStdString());
|
||||
QDialog::accept();
|
||||
});
|
||||
connect(btn_box, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
}
|
||||
|
||||
const std::optional<std::pair<std::string, std::string>>& rpcn_add_server_dialog::get_new_server() const
|
||||
{
|
||||
return m_new_server;
|
||||
}
|
||||
|
||||
rpcn_ask_username_dialog::rpcn_ask_username_dialog(QWidget* parent, const QString& description)
|
||||
: QDialog(parent)
|
||||
{
|
||||
setWindowTitle(tr("RPCN: Username"));
|
||||
setObjectName("rpcn_ask_username_dialog");
|
||||
|
||||
QVBoxLayout* vbox_global = new QVBoxLayout();
|
||||
|
||||
QLabel* lbl_username = new QLabel(description);
|
||||
|
||||
QGroupBox* grp_username = new QGroupBox(tr("Username:"));
|
||||
QHBoxLayout* hbox_grp_username = new QHBoxLayout();
|
||||
QLineEdit* edt_username = new QLineEdit(QString::fromStdString(g_cfg_rpcn.get_npid()));
|
||||
edt_username->setMaxLength(16);
|
||||
edt_username->setValidator(new QRegularExpressionValidator(QRegularExpression("^[a-zA-Z0-9_\\-]*$"), this));
|
||||
hbox_grp_username->addWidget(edt_username);
|
||||
grp_username->setLayout(hbox_grp_username);
|
||||
|
||||
QDialogButtonBox* btn_box = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
|
||||
vbox_global->addWidget(lbl_username);
|
||||
vbox_global->addWidget(grp_username);
|
||||
vbox_global->addWidget(btn_box);
|
||||
|
||||
setLayout(vbox_global);
|
||||
|
||||
connect(btn_box, &QDialogButtonBox::accepted, this, [this, edt_username]()
|
||||
{
|
||||
const auto username = edt_username->text().toStdString();
|
||||
|
||||
if (username.empty())
|
||||
{
|
||||
QMessageBox::critical(this, tr("Missing Username"), tr("You must enter a username!"), QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
if (!validate_rpcn_username(username))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Invalid Username"), tr("Please enter a valid username!"), QMessageBox::Ok);
|
||||
}
|
||||
|
||||
m_username = username;
|
||||
QDialog::accept();
|
||||
});
|
||||
connect(btn_box, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
}
|
||||
|
||||
const std::optional<std::string>& rpcn_ask_username_dialog::get_username() const
|
||||
{
|
||||
return m_username;
|
||||
}
|
||||
|
||||
rpcn_ask_password_dialog::rpcn_ask_password_dialog(QWidget* parent, const QString& description)
|
||||
: QDialog(parent)
|
||||
{
|
||||
setWindowTitle(tr("RPCN: Password"));
|
||||
setObjectName("rpcn_ask_password_dialog");
|
||||
|
||||
QVBoxLayout* vbox_global = new QVBoxLayout();
|
||||
|
||||
QLabel* lbl_description = new QLabel(description);
|
||||
|
||||
QGroupBox* gbox_password = new QGroupBox();
|
||||
QVBoxLayout* vbox_gbox = new QVBoxLayout();
|
||||
|
||||
QLabel* lbl_pass1 = new QLabel(tr("Enter your password:"));
|
||||
QLineEdit* m_edit_pass1 = new QLineEdit();
|
||||
m_edit_pass1->setEchoMode(QLineEdit::Password);
|
||||
QLabel* lbl_pass2 = new QLabel(tr("Enter your password a second time:"));
|
||||
QLineEdit* m_edit_pass2 = new QLineEdit();
|
||||
m_edit_pass2->setEchoMode(QLineEdit::Password);
|
||||
|
||||
vbox_gbox->addWidget(lbl_pass1);
|
||||
vbox_gbox->addWidget(m_edit_pass1);
|
||||
vbox_gbox->addWidget(lbl_pass2);
|
||||
vbox_gbox->addWidget(m_edit_pass2);
|
||||
gbox_password->setLayout(vbox_gbox);
|
||||
|
||||
QDialogButtonBox* btn_box = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
|
||||
vbox_global->addWidget(lbl_description);
|
||||
vbox_global->addWidget(gbox_password);
|
||||
vbox_global->addWidget(btn_box);
|
||||
|
||||
setLayout(vbox_global);
|
||||
|
||||
connect(btn_box, &QDialogButtonBox::accepted, this, [this, m_edit_pass1, m_edit_pass2]()
|
||||
{
|
||||
if (m_edit_pass1->text() != m_edit_pass2->text())
|
||||
{
|
||||
QMessageBox::critical(this, tr("Wrong Input"), tr("The two passwords you entered don't match!"), QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_edit_pass1->text().isEmpty())
|
||||
{
|
||||
QMessageBox::critical(this, tr("Missing Password"), tr("You need to enter a password!"), QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
m_password = derive_password(m_edit_pass1->text().toStdString());
|
||||
QDialog::accept();
|
||||
});
|
||||
connect(btn_box, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
}
|
||||
|
||||
const std::optional<std::string>& rpcn_ask_password_dialog::get_password() const
|
||||
{
|
||||
return m_password;
|
||||
}
|
||||
|
||||
rpcn_ask_email_dialog::rpcn_ask_email_dialog(QWidget* parent, const QString& description)
|
||||
: QDialog(parent)
|
||||
{
|
||||
setWindowTitle(tr("RPCN: Email"));
|
||||
setObjectName("rpcn_ask_email_dialog");
|
||||
|
||||
QVBoxLayout* vbox_global = new QVBoxLayout();
|
||||
|
||||
QLabel* lbl_emailinfo = new QLabel(description);
|
||||
|
||||
QGroupBox* gbox_password = new QGroupBox();
|
||||
QVBoxLayout* vbox_gbox = new QVBoxLayout();
|
||||
|
||||
QLabel* lbl_pass1 = new QLabel(tr("Enter your email:"));
|
||||
QLineEdit* m_edit_pass1 = new QLineEdit();
|
||||
QLabel* lbl_pass2 = new QLabel(tr("Enter your email a second time:"));
|
||||
QLineEdit* m_edit_pass2 = new QLineEdit();
|
||||
|
||||
vbox_gbox->addWidget(lbl_pass1);
|
||||
vbox_gbox->addWidget(m_edit_pass1);
|
||||
vbox_gbox->addWidget(lbl_pass2);
|
||||
vbox_gbox->addWidget(m_edit_pass2);
|
||||
gbox_password->setLayout(vbox_gbox);
|
||||
|
||||
QDialogButtonBox* btn_box = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
|
||||
vbox_global->addWidget(lbl_emailinfo);
|
||||
vbox_global->addWidget(gbox_password);
|
||||
vbox_global->addWidget(btn_box);
|
||||
|
||||
setLayout(vbox_global);
|
||||
|
||||
connect(btn_box, &QDialogButtonBox::accepted, this, [this, m_edit_pass1, m_edit_pass2]()
|
||||
{
|
||||
if (m_edit_pass1->text() != m_edit_pass2->text())
|
||||
{
|
||||
QMessageBox::critical(this, tr("Wrong Input"), tr("The two emails you entered don't match!"), QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_edit_pass1->text().isEmpty())
|
||||
{
|
||||
QMessageBox::critical(this, tr("Missing Email"), tr("You need to enter an email!"), QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
auto email = m_edit_pass1->text().toStdString();
|
||||
if (!validate_email(email))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Invalid Email"), tr("You need to enter a valid email!"), QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
m_email = email;
|
||||
QDialog::accept();
|
||||
});
|
||||
connect(btn_box, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
}
|
||||
|
||||
const std::optional<std::string>& rpcn_ask_email_dialog::get_email() const
|
||||
{
|
||||
return m_email;
|
||||
}
|
||||
|
||||
rpcn_ask_token_dialog::rpcn_ask_token_dialog(QWidget* parent, const QString& description)
|
||||
: QDialog(parent)
|
||||
{
|
||||
setWindowTitle(tr("RPCN: Username"));
|
||||
setObjectName("rpcn_ask_token_dialog");
|
||||
|
||||
QVBoxLayout* vbox_global = new QVBoxLayout();
|
||||
|
||||
QLabel* lbl_token = new QLabel(description);
|
||||
|
||||
QGroupBox* grp_token = new QGroupBox(tr("Token:"));
|
||||
QHBoxLayout* hbox_grp_token = new QHBoxLayout();
|
||||
QLineEdit* edt_token = new QLineEdit();
|
||||
edt_token->setMaxLength(16);
|
||||
hbox_grp_token->addWidget(edt_token);
|
||||
grp_token->setLayout(hbox_grp_token);
|
||||
|
||||
QDialogButtonBox* btn_box = new QDialogButtonBox(QDialogButtonBox::Ok);
|
||||
|
||||
vbox_global->addWidget(lbl_token);
|
||||
vbox_global->addWidget(grp_token);
|
||||
vbox_global->addWidget(btn_box);
|
||||
|
||||
setLayout(vbox_global);
|
||||
|
||||
connect(btn_box, &QDialogButtonBox::accepted, this, [this, edt_token]()
|
||||
{
|
||||
const auto token = edt_token->text().toStdString();
|
||||
|
||||
if (!token.empty())
|
||||
{
|
||||
if (!validate_token(token))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Invalid Token"), tr("The token appears to be invalid:\n"
|
||||
"-Token should be 16 characters long\n"
|
||||
"-Token should only contain 0-9 and A-F"),
|
||||
QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
m_token = token;
|
||||
}
|
||||
|
||||
QDialog::accept();
|
||||
return;
|
||||
});
|
||||
}
|
||||
|
||||
const std::optional<std::string>& rpcn_ask_token_dialog::get_token() const
|
||||
{
|
||||
return m_token;
|
||||
}
|
||||
|
||||
rpcn_account_edit_dialog::rpcn_account_edit_dialog(QWidget* parent)
|
||||
: QDialog(parent)
|
||||
{
|
||||
setWindowTitle(tr("RPCN: Edit Account"));
|
||||
setObjectName("rpcn_account_edit_dialog");
|
||||
setMinimumSize(QSize(400, 200));
|
||||
|
||||
QVBoxLayout* vbox_global = new QVBoxLayout();
|
||||
@ -76,37 +621,30 @@ rpcn_account_dialog::rpcn_account_dialog(QWidget* parent)
|
||||
QVBoxLayout* vbox_edits = new QVBoxLayout();
|
||||
QHBoxLayout* hbox_buttons = new QHBoxLayout();
|
||||
|
||||
QLabel* label_host = new QLabel(tr("Host:"));
|
||||
m_edit_host = new QLineEdit();
|
||||
QLabel* label_npid = new QLabel(tr("NPID (username):"));
|
||||
m_edit_npid = new QLineEdit();
|
||||
m_edit_npid->setMaxLength(16);
|
||||
m_edit_npid->setValidator(new QRegularExpressionValidator(QRegularExpression("^[a-zA-Z0-9_\\-]*$"), this));
|
||||
QLabel* label_pass = new QLabel(tr("Password:"));
|
||||
QLabel* lbl_username = new QLabel(tr("Username:"));
|
||||
m_edit_username = new QLineEdit();
|
||||
m_edit_username->setMaxLength(16);
|
||||
m_edit_username->setValidator(new QRegularExpressionValidator(QRegularExpression("^[a-zA-Z0-9_\\-]*$"), this));
|
||||
QLabel* lbl_pass = new QLabel(tr("Password:"));
|
||||
QPushButton* btn_chg_pass = new QPushButton(tr("Set Password"));
|
||||
QLabel* label_token = new QLabel(tr("Token:"));
|
||||
QLabel* lbl_token = new QLabel(tr("Token:"));
|
||||
m_edit_token = new QLineEdit();
|
||||
m_edit_token->setMaxLength(16);
|
||||
|
||||
QPushButton* btn_create = new QPushButton(tr("Create Account"), this);
|
||||
QPushButton* btn_resendtoken = new QPushButton(tr("Resend Token"), this);
|
||||
QPushButton* btn_changepass = new QPushButton(tr("Change Password"), this);
|
||||
btn_changepass->setEnabled(false);
|
||||
QPushButton* btn_save = new QPushButton(tr("Save"), this);
|
||||
QPushButton* btn_resendtoken = new QPushButton(tr("Resend Token"), this);
|
||||
QPushButton* btn_change_password = new QPushButton(tr("Change Password"), this);
|
||||
QPushButton* btn_save = new QPushButton(tr("Save"), this);
|
||||
|
||||
vbox_labels->addWidget(label_host);
|
||||
vbox_labels->addWidget(label_npid);
|
||||
vbox_labels->addWidget(label_pass);
|
||||
vbox_labels->addWidget(label_token);
|
||||
vbox_labels->addWidget(lbl_username);
|
||||
vbox_labels->addWidget(lbl_pass);
|
||||
vbox_labels->addWidget(lbl_token);
|
||||
|
||||
vbox_edits->addWidget(m_edit_host);
|
||||
vbox_edits->addWidget(m_edit_npid);
|
||||
vbox_edits->addWidget(m_edit_username);
|
||||
vbox_edits->addWidget(btn_chg_pass);
|
||||
vbox_edits->addWidget(m_edit_token);
|
||||
|
||||
hbox_buttons->addWidget(btn_create);
|
||||
hbox_buttons->addWidget(btn_resendtoken);
|
||||
hbox_buttons->addWidget(btn_changepass);
|
||||
hbox_buttons->addWidget(btn_change_password);
|
||||
hbox_buttons->addStretch();
|
||||
hbox_buttons->addWidget(btn_save);
|
||||
|
||||
@ -120,29 +658,14 @@ rpcn_account_dialog::rpcn_account_dialog(QWidget* parent)
|
||||
|
||||
connect(btn_chg_pass, &QAbstractButton::clicked, this, [this]()
|
||||
{
|
||||
rpcn_ask_password_dialog ask_pass;
|
||||
rpcn_ask_password_dialog ask_pass(this, tr("Please enter your password:"));
|
||||
ask_pass.exec();
|
||||
|
||||
auto password = ask_pass.get_password();
|
||||
if (!password)
|
||||
return;
|
||||
|
||||
const std::string pass_str = password.value();
|
||||
const std::string salt_str = "No matter where you go, everybody's connected.";
|
||||
|
||||
u8 salted_pass[SHA_DIGEST_SIZE];
|
||||
|
||||
wolfSSL_PKCS5_PBKDF2_HMAC_SHA1(pass_str.c_str(), pass_str.size(), reinterpret_cast<const u8*>(salt_str.c_str()), salt_str.size(), 1000, SHA_DIGEST_SIZE, salted_pass);
|
||||
|
||||
std::string hash("0000000000000000000000000000000000000000");
|
||||
for (u32 i = 0; i < 20; i++)
|
||||
{
|
||||
constexpr auto pal = "0123456789abcdef";
|
||||
hash[i * 2] = pal[salted_pass[i] >> 4];
|
||||
hash[1 + i * 2] = pal[salted_pass[i] & 15];
|
||||
}
|
||||
|
||||
g_cfg_rpcn.set_password(hash);
|
||||
g_cfg_rpcn.set_password(*password);
|
||||
g_cfg_rpcn.save();
|
||||
|
||||
QMessageBox::information(this, tr("RPCN Password Saved"), tr("Your password was saved successfully!"), QMessageBox::Ok);
|
||||
@ -153,48 +676,39 @@ rpcn_account_dialog::rpcn_account_dialog(QWidget* parent)
|
||||
if (save_config())
|
||||
close();
|
||||
});
|
||||
connect(btn_create, &QAbstractButton::clicked, this, &rpcn_account_dialog::create_account);
|
||||
connect(btn_resendtoken, &QAbstractButton::clicked, this, &rpcn_account_dialog::resend_token);
|
||||
connect(btn_resendtoken, &QAbstractButton::clicked, this, &rpcn_account_edit_dialog::resend_token);
|
||||
connect(btn_change_password, &QAbstractButton::clicked, this, &rpcn_account_edit_dialog::change_password);
|
||||
|
||||
g_cfg_rpcn.load();
|
||||
|
||||
m_edit_host->setText(QString::fromStdString(g_cfg_rpcn.get_host()));
|
||||
m_edit_npid->setText(QString::fromStdString(g_cfg_rpcn.get_npid()));
|
||||
m_edit_username->setText(QString::fromStdString(g_cfg_rpcn.get_npid()));
|
||||
m_edit_token->setText(QString::fromStdString(g_cfg_rpcn.get_token()));
|
||||
}
|
||||
|
||||
bool rpcn_account_dialog::save_config()
|
||||
bool rpcn_account_edit_dialog::save_config()
|
||||
{
|
||||
const auto host = m_edit_host->text().toStdString();
|
||||
const auto npid = m_edit_npid->text().toStdString();
|
||||
const auto token = m_edit_token->text().toStdString();
|
||||
const auto username = m_edit_username->text().toStdString();
|
||||
const auto token = m_edit_token->text().toStdString();
|
||||
|
||||
if (host.empty())
|
||||
if (username.empty() || g_cfg_rpcn.get_password().empty())
|
||||
{
|
||||
QMessageBox::critical(this, tr("Missing host"), tr("You need to enter a host for rpcn!"), QMessageBox::Ok);
|
||||
QMessageBox::critical(this, tr("Missing Input"), tr("You need to enter a username and a password!"), QMessageBox::Ok);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (npid.empty() || g_cfg_rpcn.get_password().empty())
|
||||
if (!validate_rpcn_username(username))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Wrong input"), tr("You need to enter a username and a password!"), QMessageBox::Ok);
|
||||
QMessageBox::critical(this, tr("Invalid Username"), tr("Username must be between 3 and 16 characters and can only contain '-', '_' or alphanumeric characters."), QMessageBox::Ok);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!validate_rpcn_username(npid))
|
||||
if (!token.empty() && !validate_token(token))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Invalid character"), tr("NPID must be between 3 and 16 characters and can only contain '-', '_' or alphanumeric characters."), QMessageBox::Ok);
|
||||
QMessageBox::critical(this, tr("Invalid Token"), tr("The token you have received should be 16 characters long and contain only 0-9 A-F."), QMessageBox::Ok);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!token.empty() && token.size() != 16)
|
||||
{
|
||||
QMessageBox::critical(this, tr("Invalid token"), tr("The token you have received should be 16 characters long."), QMessageBox::Ok);
|
||||
return false;
|
||||
}
|
||||
|
||||
g_cfg_rpcn.set_host(host);
|
||||
g_cfg_rpcn.set_npid(npid);
|
||||
g_cfg_rpcn.set_npid(username);
|
||||
g_cfg_rpcn.set_token(token);
|
||||
|
||||
g_cfg_rpcn.save();
|
||||
@ -202,66 +716,7 @@ bool rpcn_account_dialog::save_config()
|
||||
return true;
|
||||
}
|
||||
|
||||
void rpcn_account_dialog::create_account()
|
||||
{
|
||||
// Validate and save
|
||||
if (!save_config())
|
||||
return;
|
||||
|
||||
QString email;
|
||||
const QRegularExpressionValidator simple_email_validator(QRegularExpression("^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*$"));
|
||||
|
||||
while (true)
|
||||
{
|
||||
bool clicked_ok = false;
|
||||
email = QInputDialog::getText(this, tr("Email address"), tr("An email address is required, please note:\n*A valid email is needed to validate your account.\n*Your email won't be used for anything beyond sending you the token.\n*Upon successful creation a token will be sent to your email which you'll need to login.\n\n"), QLineEdit::Normal, "", &clicked_ok);
|
||||
if (!clicked_ok)
|
||||
return;
|
||||
|
||||
int pos = 0;
|
||||
if (email.isEmpty() || simple_email_validator.validate(email, pos) != QValidator::Acceptable)
|
||||
{
|
||||
QMessageBox::critical(this, tr("Wrong input"), tr("You need to enter a valid email!"), QMessageBox::Ok);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const auto rpcn = rpcn::rpcn_client::get_instance();
|
||||
|
||||
const auto npid = g_cfg_rpcn.get_npid();
|
||||
const auto online_name = npid;
|
||||
const auto avatar_url = "https://rpcs3.net/cdn/netplay/DefaultAvatar.png";
|
||||
const auto password = g_cfg_rpcn.get_password();
|
||||
|
||||
if (auto result = rpcn->wait_for_connection(); result != rpcn::rpcn_state::failure_no_failure)
|
||||
{
|
||||
const QString error_message = tr("Failed to connect to RPCN server:\n%0").arg(QString::fromStdString(rpcn::rpcn_state_to_string(result)));
|
||||
QMessageBox::critical(this, tr("Error Connecting"), error_message, QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
if (auto error = rpcn->create_user(npid, password, online_name, avatar_url, email.toStdString()); error != rpcn::ErrorType::NoError)
|
||||
{
|
||||
QString error_message;
|
||||
switch (error)
|
||||
{
|
||||
case rpcn::ErrorType::CreationExistingUsername: error_message = tr("An account with that username already exists!"); break;
|
||||
case rpcn::ErrorType::CreationBannedEmailProvider: error_message = tr("This email provider is banned!"); break;
|
||||
case rpcn::ErrorType::CreationExistingEmail: error_message = tr("An account with that email already exists!"); break;
|
||||
case rpcn::ErrorType::CreationError: error_message = tr("Unknown creation error"); break;
|
||||
default: error_message = tr("Unknown error"); break;
|
||||
}
|
||||
QMessageBox::critical(this, tr("Error Creating Account"), tr("Failed to create the account:\n%0").arg(error_message), QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
QMessageBox::information(this, tr("Account created!"), tr("Your account has been created successfully!\nCheck your email for your token!"), QMessageBox::Ok);
|
||||
}
|
||||
|
||||
void rpcn_account_dialog::resend_token()
|
||||
void rpcn_account_edit_dialog::resend_token()
|
||||
{
|
||||
if (!save_config())
|
||||
return;
|
||||
@ -284,11 +739,10 @@ void rpcn_account_dialog::resend_token()
|
||||
switch (error)
|
||||
{
|
||||
case rpcn::ErrorType::Invalid: error_message = tr("The server has no email verification and doesn't need a token!"); break;
|
||||
case rpcn::ErrorType::LoginAlreadyLoggedIn: error_message = tr("You can't ask for your token while authentified!"); break;
|
||||
case rpcn::ErrorType::DbFail: error_message = tr("A database related error happened on the server!"); break;
|
||||
case rpcn::ErrorType::TooSoon: error_message = tr("You can only ask for a token mail once every 24 hours!"); break;
|
||||
case rpcn::ErrorType::EmailFail: error_message = tr("The mail couldn't be sent successfully!"); break;
|
||||
case rpcn::ErrorType::LoginError: error_message = tr("The login/password pair is invalid!"); break;
|
||||
case rpcn::ErrorType::LoginError: error_message = tr("The username/password pair is invalid!"); break;
|
||||
default: error_message = tr("Unknown error"); break;
|
||||
}
|
||||
QMessageBox::critical(this, tr("Error Sending Token"), tr("Failed to send the token:\n%0").arg(error_message), QMessageBox::Ok);
|
||||
@ -298,64 +752,102 @@ void rpcn_account_dialog::resend_token()
|
||||
QMessageBox::information(this, tr("Token Sent!"), tr("Your token was successfully resent to the email associated with your account!"), QMessageBox::Ok);
|
||||
}
|
||||
|
||||
rpcn_ask_password_dialog::rpcn_ask_password_dialog(QWidget* parent)
|
||||
: QDialog(parent)
|
||||
void rpcn_account_edit_dialog::change_password()
|
||||
{
|
||||
QVBoxLayout* vbox_global = new QVBoxLayout();
|
||||
QHBoxLayout* hbox_buttons = new QHBoxLayout();
|
||||
rpcn_ask_username_dialog dlg_username(this, tr("Please confirm your username:"));
|
||||
dlg_username.exec();
|
||||
auto username = dlg_username.get_username();
|
||||
|
||||
QGroupBox* gbox_password = new QGroupBox();
|
||||
QVBoxLayout* vbox_gbox = new QVBoxLayout();
|
||||
if (!username)
|
||||
return;
|
||||
|
||||
QLabel* label_pass1 = new QLabel(tr("Enter your password:"));
|
||||
m_edit_pass1 = new QLineEdit();
|
||||
m_edit_pass1->setEchoMode(QLineEdit::Password);
|
||||
QLabel* label_pass2 = new QLabel(tr("Enter your password a second time:"));
|
||||
m_edit_pass2 = new QLineEdit();
|
||||
m_edit_pass2->setEchoMode(QLineEdit::Password);
|
||||
switch (QMessageBox::question(this, tr("RPCN: Change Password"), tr("Do you already have a reset password token?\n"
|
||||
"Note that the reset password token is different from the email verification token.")))
|
||||
{
|
||||
case QMessageBox::No:
|
||||
{
|
||||
rpcn_ask_email_dialog dlg_email(this, tr("Please enter the email you used to create the account:"));
|
||||
dlg_email.exec();
|
||||
const auto email = dlg_email.get_email();
|
||||
|
||||
vbox_gbox->addWidget(label_pass1);
|
||||
vbox_gbox->addWidget(m_edit_pass1);
|
||||
vbox_gbox->addWidget(label_pass2);
|
||||
vbox_gbox->addWidget(m_edit_pass2);
|
||||
gbox_password->setLayout(vbox_gbox);
|
||||
if (!email)
|
||||
return;
|
||||
|
||||
QPushButton* btn_ok = new QPushButton(tr("Ok"));
|
||||
QPushButton* btn_cancel = new QPushButton(tr("Cancel"));
|
||||
|
||||
hbox_buttons->addStretch();
|
||||
hbox_buttons->addWidget(btn_ok);
|
||||
hbox_buttons->addWidget(btn_cancel);
|
||||
|
||||
vbox_global->addWidget(gbox_password);
|
||||
vbox_global->addLayout(hbox_buttons);
|
||||
|
||||
setLayout(vbox_global);
|
||||
|
||||
connect(btn_ok, &QAbstractButton::clicked, this, [this]()
|
||||
{
|
||||
if (m_edit_pass1->text() != m_edit_pass2->text())
|
||||
const auto rpcn = rpcn::rpcn_client::get_instance();
|
||||
if (auto result = rpcn->wait_for_connection(); result != rpcn::rpcn_state::failure_no_failure)
|
||||
{
|
||||
QMessageBox::critical(this, tr("Wrong input"), tr("The two passwords you entered don't match!"), QMessageBox::Ok);
|
||||
const QString error_message = tr("Failed to connect to RPCN server:\n%0").arg(QString::fromStdString(rpcn::rpcn_state_to_string(result)));
|
||||
QMessageBox::critical(this, tr("Error Connecting"), error_message, QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_edit_pass1->text().isEmpty())
|
||||
if (auto error = rpcn->send_reset_token(*username, *email); error != rpcn::ErrorType::NoError)
|
||||
{
|
||||
QMessageBox::critical(this, tr("Wrong input"), tr("You need to enter a password!"), QMessageBox::Ok);
|
||||
QString error_message;
|
||||
switch (error)
|
||||
{
|
||||
case rpcn::ErrorType::Invalid: error_message = tr("The server has no email verification and doesn't support password changes!"); break;
|
||||
case rpcn::ErrorType::DbFail: error_message = tr("A database related error happened on the server!"); break;
|
||||
case rpcn::ErrorType::TooSoon: error_message = tr("You can only ask for a reset password token once every 24 hours!"); break;
|
||||
case rpcn::ErrorType::EmailFail: error_message = tr("The mail couldn't be sent successfully!"); break;
|
||||
case rpcn::ErrorType::LoginError: error_message = tr("The username/email pair is invalid!"); break;
|
||||
default: error_message = tr("Unknown error"); break;
|
||||
}
|
||||
QMessageBox::critical(this, tr("Error Sending Password Reset Token"), tr("Failed to send the password reset token:\n%0").arg(error_message), QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
m_password = m_edit_pass1->text().toStdString();
|
||||
close();
|
||||
});
|
||||
connect(btn_cancel, &QAbstractButton::clicked, this, [this]()
|
||||
{ this->close(); });
|
||||
}
|
||||
QMessageBox::information(this, tr("Password Reset Token Sent!"), tr("The reset password token has successfully been sent!"), QMessageBox::Ok);
|
||||
}
|
||||
}
|
||||
case QMessageBox::Yes:
|
||||
{
|
||||
rpcn_ask_token_dialog dlg_token(this, tr("Please enter the password reset token you received:"));
|
||||
dlg_token.exec();
|
||||
const auto token = dlg_token.get_token();
|
||||
|
||||
std::optional<std::string> rpcn_ask_password_dialog::get_password()
|
||||
{
|
||||
return m_password;
|
||||
if (!token)
|
||||
return;
|
||||
|
||||
rpcn_ask_password_dialog dlg_password(this, tr("Please enter your new password:"));
|
||||
dlg_password.exec();
|
||||
const auto password = dlg_password.get_password();
|
||||
|
||||
if (!password)
|
||||
return;
|
||||
|
||||
{
|
||||
const auto rpcn = rpcn::rpcn_client::get_instance();
|
||||
if (auto result = rpcn->wait_for_connection(); result != rpcn::rpcn_state::failure_no_failure)
|
||||
{
|
||||
const QString error_message = tr("Failed to connect to RPCN server:\n%0").arg(QString::fromStdString(rpcn::rpcn_state_to_string(result)));
|
||||
QMessageBox::critical(this, tr("Error Connecting"), error_message, QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
if (auto error = rpcn->reset_password(*username, *token, *password); error != rpcn::ErrorType::NoError)
|
||||
{
|
||||
QString error_message;
|
||||
switch (error)
|
||||
{
|
||||
case rpcn::ErrorType::Invalid: error_message = tr("The server has no email verification and doesn't support password changes!"); break;
|
||||
case rpcn::ErrorType::DbFail: error_message = tr("A database related error happened on the server!"); break;
|
||||
case rpcn::ErrorType::TooSoon: error_message = tr("You can only ask for a reset password token once every 24 hours!"); break;
|
||||
case rpcn::ErrorType::EmailFail: error_message = tr("The mail couldn't be sent successfully!"); break;
|
||||
case rpcn::ErrorType::LoginError: error_message = tr("The username/token pair is invalid!"); break;
|
||||
default: error_message = tr("Unknown error"); break;
|
||||
}
|
||||
QMessageBox::critical(this, tr("Error Sending Password Reset Token"), tr("Failed to change the password:\n%0").arg(error_message), QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
QMessageBox::information(this, tr("Password Successfully Changed!"), tr("Your password has been successfully changed!"), QMessageBox::Ok);
|
||||
}
|
||||
}
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void friend_callback(void* param, rpcn::NotificationType ntype, const std::string& username, bool status)
|
||||
@ -636,7 +1128,7 @@ void rpcn_friends_dialog::callback_handler(rpcn::NotificationType ntype, std::st
|
||||
}
|
||||
default:
|
||||
{
|
||||
rpcn_settings_log.fatal("An unhandled notification type was received by the rpcn friends dialog callback!");
|
||||
rpcn_settings_log.fatal("An unhandled notification type was received by the RPCN friends dialog callback!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -22,28 +22,84 @@ public:
|
||||
rpcn_account_dialog(QWidget* parent = nullptr);
|
||||
|
||||
private:
|
||||
bool save_config();
|
||||
void refresh_combobox();
|
||||
|
||||
private Q_SLOTS:
|
||||
void create_account();
|
||||
void resend_token();
|
||||
private:
|
||||
QComboBox* cbx_servers = nullptr;
|
||||
};
|
||||
|
||||
protected:
|
||||
QLineEdit *m_edit_host, *m_edit_npid, *m_edit_token;
|
||||
class rpcn_add_server_dialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
rpcn_add_server_dialog(QWidget* parent = nullptr);
|
||||
const std::optional<std::pair<std::string, std::string>>& get_new_server() const;
|
||||
|
||||
private:
|
||||
std::optional<std::pair<std::string, std::string>> m_new_server;
|
||||
};
|
||||
|
||||
class rpcn_ask_username_dialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
rpcn_ask_username_dialog(QWidget* parent, const QString& description);
|
||||
const std::optional<std::string>& get_username() const;
|
||||
|
||||
private:
|
||||
std::optional<std::string> m_username;
|
||||
};
|
||||
|
||||
class rpcn_ask_password_dialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
rpcn_ask_password_dialog(QWidget* parent = nullptr);
|
||||
std::optional<std::string> get_password();
|
||||
rpcn_ask_password_dialog(QWidget* parent, const QString& description);
|
||||
const std::optional<std::string>& get_password() const;
|
||||
|
||||
private:
|
||||
QLineEdit *m_edit_pass1, *m_edit_pass2;
|
||||
std::optional<std::string> m_password;
|
||||
};
|
||||
|
||||
class rpcn_ask_email_dialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
rpcn_ask_email_dialog(QWidget* parent, const QString& description);
|
||||
const std::optional<std::string>& get_email() const;
|
||||
|
||||
private:
|
||||
std::optional<std::string> m_email;
|
||||
};
|
||||
|
||||
class rpcn_ask_token_dialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
rpcn_ask_token_dialog(QWidget* parent, const QString& description);
|
||||
const std::optional<std::string>& get_token() const;
|
||||
|
||||
private:
|
||||
std::optional<std::string> m_token;
|
||||
};
|
||||
|
||||
class rpcn_account_edit_dialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
rpcn_account_edit_dialog(QWidget* parent = nullptr);
|
||||
|
||||
private:
|
||||
bool save_config();
|
||||
|
||||
private Q_SLOTS:
|
||||
void resend_token();
|
||||
void change_password();
|
||||
|
||||
protected:
|
||||
QLineEdit *m_edit_username, *m_edit_token;
|
||||
};
|
||||
|
||||
class rpcn_friends_dialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
Loading…
Reference in New Issue
Block a user