mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-25 12:12:50 +01:00
rpcn v0.4.0
This commit is contained in:
parent
15af1bca69
commit
ea9dc9317d
2
3rdparty/flatbuffers
vendored
2
3rdparty/flatbuffers
vendored
@ -1 +1 @@
|
||||
Subproject commit 9e7e8cbe9f675123dd41b7c62868acad39188cae
|
||||
Subproject commit a9a295fecf3fbd5a4f571f53b01f63202a3e2113
|
2
3rdparty/wolfssl/CMakeLists.txt
vendored
2
3rdparty/wolfssl/CMakeLists.txt
vendored
@ -7,7 +7,7 @@ else()
|
||||
# TODO(cjj19970505@live.cn)
|
||||
# OPENSSL_EXTRA, WOLFSSL_DES_ECB 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)
|
||||
add_compile_definitions(OPENSSL_EXTRA WOLFSSL_DES_ECB HAVE_SNI HAVE_WRITE_DUP)
|
||||
|
||||
set(WOLFSSL_TLS13 "no" CACHE INTERNAL "")
|
||||
set(WOLFSSL_SHA224 "yes" CACHE INTERNAL "")
|
||||
|
4
3rdparty/wolfssl/wolfssl.vcxproj
vendored
4
3rdparty/wolfssl/wolfssl.vcxproj
vendored
@ -48,7 +48,7 @@
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>./wolfssl;./wolfssl/IDE/WIN;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WOLFSSL_LIB;WOLFSSL_DES_ECB;HAVE_FFDHE_2048;TFM_TIMING_RESISTANT;ECC_TIMING_RESISTANT;WC_RSA_BLINDING;HAVE_AESGCM;WOLFSSL_SHA512;WOLFSSL_SHA384;NO_DSA;HAVE_ECC;TFM_ECC256;ECC_SHAMIR;NO_RC4;NO_HC128;NO_RABBIT;WOLFSSL_SHA224;WOLFSSL_SHA3;WOLFSSL_SHAKE256;HAVE_POLY1305;HAVE_ONE_TIME_AUTH;HAVE_CHACHA;HAVE_HASHDRBG;HAVE_TLS_EXTENSIONS;HAVE_SNI;HAVE_SUPPORTED_CURVES;HAVE_EXTENDED_MASTER;NO_RC4;HAVE_ENCRYPT_THEN_MAC;NO_PSK;NO_MD4;WC_NO_ASYNC_THREADING;OPENSSL_EXTRA;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>WOLFSSL_LIB;WOLFSSL_DES_ECB;HAVE_FFDHE_2048;TFM_TIMING_RESISTANT;NO_DSA;TFM_ECC256;NO_RC4;NO_HC128;NO_RABBIT;WOLFSSL_SHA224;WOLFSSL_SHA3;WOLFSSL_SHAKE256;HAVE_POLY1305;HAVE_ONE_TIME_AUTH;HAVE_CHACHA;HAVE_HASHDRBG;HAVE_SNI;HAVE_ENCRYPT_THEN_MAC;NO_MD4;WC_NO_ASYNC_THREADING;CYASSL_USER_SETTINGS;WC_NO_HARDEN;HAVE_WRITE_DUP;WC_RSA_BLINDING;NO_MULTIBYTE_PRINT;OPENSSL_EXTRA;WOLFSSL_RIPEMD;NO_PSK;HAVE_EXTENDED_MASTER;WOLFSSL_SNIFFER;HAVE_AESGCM;WOLFSSL_SHA384;WOLFSSL_SHA512;HAVE_SUPPORTED_CURVES;HAVE_TLS_EXTENSIONS;HAVE_ECC;ECC_SHAMIR;ECC_TIMING_RESISTANT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
@ -62,7 +62,7 @@
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>./wolfssl;./wolfssl/IDE/WIN;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WOLFSSL_LIB;WOLFSSL_DES_ECB;HAVE_FFDHE_2048;TFM_TIMING_RESISTANT;NO_DSA;TFM_ECC256;NO_RC4;NO_HC128;NO_RABBIT;WOLFSSL_SHA224;WOLFSSL_SHA3;WOLFSSL_SHAKE256;HAVE_POLY1305;HAVE_ONE_TIME_AUTH;HAVE_CHACHA;HAVE_HASHDRBG;HAVE_SNI;HAVE_ENCRYPT_THEN_MAC;NO_MD4;WC_NO_ASYNC_THREADING;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;WC_NO_HARDEN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>WOLFSSL_LIB;WOLFSSL_DES_ECB;HAVE_FFDHE_2048;TFM_TIMING_RESISTANT;NO_DSA;TFM_ECC256;NO_RC4;NO_HC128;NO_RABBIT;WOLFSSL_SHA224;WOLFSSL_SHA3;WOLFSSL_SHAKE256;HAVE_POLY1305;HAVE_ONE_TIME_AUTH;HAVE_CHACHA;HAVE_HASHDRBG;HAVE_SNI;HAVE_ENCRYPT_THEN_MAC;NO_MD4;WC_NO_ASYNC_THREADING;CYASSL_USER_SETTINGS;WC_NO_HARDEN;HAVE_WRITE_DUP;WC_RSA_BLINDING;NO_MULTIBYTE_PRINT;OPENSSL_EXTRA;WOLFSSL_RIPEMD;NO_PSK;HAVE_EXTENDED_MASTER;WOLFSSL_SNIFFER;HAVE_AESGCM;WOLFSSL_SHA384;WOLFSSL_SHA512;HAVE_SUPPORTED_CURVES;HAVE_TLS_EXTENSIONS;HAVE_ECC;ECC_SHAMIR;ECC_TIMING_RESISTANT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
|
@ -110,6 +110,15 @@ error_code cellSysutilAvc2StartVoiceDetection()
|
||||
error_code cellSysutilAvc2UnloadAsync()
|
||||
{
|
||||
cellSysutilAvc2.todo("cellSysutilAvc2UnloadAsync()");
|
||||
|
||||
if (avc2_cb)
|
||||
{
|
||||
sysutil_register_cb([=](ppu_thread& cb_ppu) -> s32 {
|
||||
avc2_cb(cb_ppu, CELL_AVC2_EVENT_UNLOAD_SUCCEEDED, 0, avc2_cb_arg);
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,8 @@
|
||||
#include "Emu/system_utils.hpp"
|
||||
#include "Emu/VFS.h"
|
||||
#include "Emu/Cell/PPUModule.h"
|
||||
#include "Emu/Io/interception.h"
|
||||
#include "Utilities/StrUtil.h"
|
||||
|
||||
#include "sysPrxForUser.h"
|
||||
#include "Emu/IdManager.h"
|
||||
@ -396,6 +398,11 @@ void fmt_class_string<SceNpError>::format(std::string& out, u64 arg)
|
||||
});
|
||||
}
|
||||
|
||||
void message_data::print() const
|
||||
{
|
||||
sceNp.notice("commId: %s, msgId: %d, mainType: %d, subType: %d, subject: %s, body: %s, data_size: %d", static_cast<const char *>(commId.data), msgId, mainType, subType, subject, body, data.size());
|
||||
}
|
||||
|
||||
error_code sceNpInit(u32 poolsize, vm::ptr<void> poolptr)
|
||||
{
|
||||
sceNp.warning("sceNpInit(poolsize=0x%x, poolptr=*0x%x)", poolsize, poolptr);
|
||||
@ -629,7 +636,7 @@ error_code sceNpDrmProcessExitSpawn2(ppu_thread& ppu, vm::cptr<u8> klicensee, vm
|
||||
|
||||
error_code sceNpBasicRegisterHandler(vm::cptr<SceNpCommunicationId> context, vm::ptr<SceNpBasicEventHandler> handler, vm::ptr<void> arg)
|
||||
{
|
||||
sceNp.warning("sceNpBasicRegisterHandler(context=*0x%x, handler=*0x%x, arg=*0x%x)", context, handler, arg);
|
||||
sceNp.warning("sceNpBasicRegisterHandler(context=*0x%x(%s), handler=*0x%x, arg=*0x%x)", context, context ? static_cast<const char *>(context->data) : "", handler, arg);
|
||||
|
||||
auto& nph = g_fxo->get<named_thread<np_handler>>();
|
||||
|
||||
@ -638,13 +645,21 @@ error_code sceNpBasicRegisterHandler(vm::cptr<SceNpCommunicationId> context, vm:
|
||||
return SCE_NP_BASIC_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
if (nph.basic_handler.registered)
|
||||
{
|
||||
return SCE_NP_BASIC_ERROR_EXCEEDS_MAX;
|
||||
}
|
||||
|
||||
if (!context || !handler)
|
||||
{
|
||||
return SCE_NP_BASIC_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
nph.basic_handler = handler;
|
||||
nph.basic_handler_arg = arg;
|
||||
memcpy(&nph.basic_handler.context, context.get_ptr(), sizeof(nph.basic_handler.context));
|
||||
nph.basic_handler.handler_func = handler;
|
||||
nph.basic_handler.handler_arg = arg;
|
||||
nph.basic_handler.registered = true;
|
||||
nph.basic_handler.context_sensitive = false;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -660,11 +675,22 @@ error_code sceNpBasicRegisterContextSensitiveHandler(vm::cptr<SceNpCommunication
|
||||
return SCE_NP_BASIC_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
if (nph.basic_handler.registered)
|
||||
{
|
||||
return SCE_NP_BASIC_ERROR_EXCEEDS_MAX;
|
||||
}
|
||||
|
||||
if (!context || !handler)
|
||||
{
|
||||
return SCE_NP_BASIC_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
memcpy(&nph.basic_handler.context, context.get_ptr(), sizeof(nph.basic_handler.context));
|
||||
nph.basic_handler.handler_func = handler;
|
||||
nph.basic_handler.handler_arg = arg;
|
||||
nph.basic_handler.registered = true;
|
||||
nph.basic_handler.context_sensitive = true;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@ -679,6 +705,13 @@ error_code sceNpBasicUnregisterHandler()
|
||||
return SCE_NP_BASIC_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
if (!nph.basic_handler.registered)
|
||||
{
|
||||
return SCE_NP_BASIC_ERROR_NOT_REGISTERED;
|
||||
}
|
||||
|
||||
nph.basic_handler.registered = false;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@ -775,7 +808,18 @@ error_code sceNpBasicSendMessage(vm::cptr<SceNpId> to, vm::cptr<void> data, u64
|
||||
|
||||
error_code sceNpBasicSendMessageGui(vm::cptr<SceNpBasicMessageDetails> msg, sys_memory_container_t containerId)
|
||||
{
|
||||
sceNp.todo("sceNpBasicSendMessageGui(msg=*0x%x, containerId=%d)", msg, containerId);
|
||||
sceNp.warning("sceNpBasicSendMessageGui(msg=*0x%x, containerId=%d)", msg, containerId);
|
||||
|
||||
if (msg)
|
||||
{
|
||||
sceNp.notice("sceNpBasicSendMessageGui: msgId: %d, mainType: %d, subType: %d, msgFeatures: %d, count: %d", msg->msgId, msg->mainType, msg->subType, msg->msgFeatures, msg->count);
|
||||
for (u32 i = 0; i < msg->count; i++)
|
||||
{
|
||||
sceNp.trace("sceNpBasicSendMessageGui: NpId[%d] = %s", i, static_cast<char*>(&msg->npids[i].handle.data[0]));
|
||||
}
|
||||
sceNp.notice("sceNpBasicSendMessageGui: subject: %s", msg->subject);
|
||||
sceNp.notice("sceNpBasicSendMessageGui: body: %s", msg->body);
|
||||
}
|
||||
|
||||
auto& nph = g_fxo->get<named_thread<np_handler>>();
|
||||
|
||||
@ -784,7 +828,13 @@ error_code sceNpBasicSendMessageGui(vm::cptr<SceNpBasicMessageDetails> msg, sys_
|
||||
return SCE_NP_BASIC_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
if (!msg || msg->count > SCE_NP_BASIC_SEND_MESSAGE_MAX_RECIPIENTS || msg->npids.handle.data[0] == '\0' || !(msg->msgFeatures & SCE_NP_BASIC_MESSAGE_FEATURES_ALL_FEATURES))
|
||||
if (!nph.basic_handler.registered)
|
||||
{
|
||||
return SCE_NP_BASIC_ERROR_NOT_REGISTERED;
|
||||
}
|
||||
|
||||
if (!msg || msg->count > SCE_NP_BASIC_SEND_MESSAGE_MAX_RECIPIENTS || (msg->msgFeatures & ~SCE_NP_BASIC_MESSAGE_FEATURES_ALL_FEATURES) ||
|
||||
msg->mainType > SCE_NP_BASIC_MESSAGE_MAIN_TYPE_URL_ATTACHMENT || msg->msgId != 0ull)
|
||||
{
|
||||
return SCE_NP_BASIC_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
@ -799,6 +849,82 @@ error_code sceNpBasicSendMessageGui(vm::cptr<SceNpBasicMessageDetails> msg, sys_
|
||||
return not_an_error(SCE_NP_BASIC_ERROR_NOT_CONNECTED);
|
||||
}
|
||||
|
||||
// Prepare message data
|
||||
message_data msg_data = {
|
||||
.commId = nph.basic_handler.context,
|
||||
.msgId = msg->msgId,
|
||||
.mainType = msg->mainType,
|
||||
.subType = msg->subType,
|
||||
.msgFeatures = msg->msgFeatures};
|
||||
std::set<std::string> npids;
|
||||
|
||||
for (u32 i = 0; i < msg->count; i++)
|
||||
{
|
||||
npids.insert(std::string(msg->npids[i].handle.data));
|
||||
}
|
||||
|
||||
if (msg->subject)
|
||||
{
|
||||
msg_data.subject = std::string(msg->subject.get_ptr());
|
||||
}
|
||||
|
||||
if (msg->body)
|
||||
{
|
||||
msg_data.body = std::string(msg->body.get_ptr());
|
||||
}
|
||||
|
||||
if (msg->size)
|
||||
{
|
||||
msg_data.data.assign(msg->data.get_ptr(), msg->data.get_ptr() + msg->size);
|
||||
}
|
||||
|
||||
atomic_t<bool> wake_up = false;
|
||||
bool result = false;
|
||||
|
||||
input::SetIntercepted(true);
|
||||
|
||||
Emu.CallAfter([=, &wake_up, &result, msg_data = std::move(msg_data), npids = std::move(npids)]() mutable
|
||||
{
|
||||
auto send_dlg = Emu.GetCallbacks().get_sendmessage_dialog();
|
||||
result = send_dlg->Exec(msg_data, npids);
|
||||
wake_up = true;
|
||||
wake_up.notify_one();
|
||||
});
|
||||
|
||||
while (!wake_up && !Emu.IsStopped())
|
||||
{
|
||||
thread_ctrl::wait_on(wake_up, false);
|
||||
}
|
||||
|
||||
input::SetIntercepted(false);
|
||||
|
||||
s32 callback_result = result ? 0 : -1;
|
||||
s32 event = 0;
|
||||
|
||||
switch (msg->mainType)
|
||||
{
|
||||
case SCE_NP_BASIC_MESSAGE_MAIN_TYPE_DATA_ATTACHMENT:
|
||||
event = SCE_NP_BASIC_EVENT_SEND_ATTACHMENT_RESULT;
|
||||
break;
|
||||
case SCE_NP_BASIC_MESSAGE_MAIN_TYPE_GENERAL:
|
||||
event = SCE_NP_BASIC_EVENT_SEND_MESSAGE_RESULT;
|
||||
break;
|
||||
case SCE_NP_BASIC_MESSAGE_MAIN_TYPE_ADD_FRIEND:
|
||||
event = SCE_NP_BASIC_EVENT_ADD_FRIEND_RESULT;
|
||||
break;
|
||||
case SCE_NP_BASIC_MESSAGE_MAIN_TYPE_INVITE:
|
||||
event = SCE_NP_BASIC_EVENT_SEND_INVITATION_RESULT;
|
||||
break;
|
||||
case SCE_NP_BASIC_MESSAGE_MAIN_TYPE_CUSTOM_DATA:
|
||||
event = SCE_NP_BASIC_EVENT_SEND_CUSTOM_DATA_RESULT;
|
||||
break;
|
||||
case SCE_NP_BASIC_MESSAGE_MAIN_TYPE_URL_ATTACHMENT:
|
||||
event = SCE_NP_BASIC_EVENT_SEND_URL_ATTACHMENT_RESULT;
|
||||
break;
|
||||
}
|
||||
|
||||
nph.send_basic_event(event, callback_result, 0);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@ -845,9 +971,9 @@ error_code sceNpBasicRecvMessageAttachment(sys_memory_container_t containerId)
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code sceNpBasicRecvMessageAttachmentLoad(u32 id, vm::ptr<void> buffer, vm::ptr<u64> size)
|
||||
error_code sceNpBasicRecvMessageAttachmentLoad(u32 id, vm::ptr<void> buffer, vm::ptr<u32> size)
|
||||
{
|
||||
sceNp.todo("sceNpBasicRecvMessageAttachmentLoad(id=%d, buffer=*0x%x, size=*0x%x)", id, buffer, size);
|
||||
sceNp.warning("sceNpBasicRecvMessageAttachmentLoad(id=%d, buffer=*0x%x, size=*0x%x)", id, buffer, size);
|
||||
|
||||
auto& nph = g_fxo->get<named_thread<np_handler>>();
|
||||
|
||||
@ -856,22 +982,41 @@ error_code sceNpBasicRecvMessageAttachmentLoad(u32 id, vm::ptr<void> buffer, vm:
|
||||
return SCE_NP_BASIC_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
if (!nph.basic_handler.registered)
|
||||
{
|
||||
return SCE_NP_BASIC_ERROR_NOT_REGISTERED;
|
||||
}
|
||||
|
||||
if (!buffer || !size)
|
||||
{
|
||||
return SCE_NP_BASIC_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
if (id > SCE_NP_BASIC_SELECTED_MESSAGE_DATA)
|
||||
const auto opt_msg = nph.get_message(id);
|
||||
if (!opt_msg)
|
||||
{
|
||||
return SCE_NP_BASIC_ERROR_INVALID_DATA_ID;
|
||||
}
|
||||
|
||||
const auto msg_pair = opt_msg.value();
|
||||
const auto msg = msg_pair->second;
|
||||
|
||||
const u32 orig_size = *size;
|
||||
const u32 size_to_copy = std::min(static_cast<u32>(msg.data.size()), orig_size);
|
||||
memcpy(buffer.get_ptr(), msg.data.data(), size_to_copy);
|
||||
|
||||
*size = size_to_copy;
|
||||
if (size_to_copy < msg.data.size())
|
||||
{
|
||||
return SCE_NP_BASIC_ERROR_DATA_LOST;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code sceNpBasicRecvMessageCustom(u16 mainType, u32 recvOptions, sys_memory_container_t containerId)
|
||||
{
|
||||
sceNp.todo("sceNpBasicRecvMessageCustom(mainType=%d, recvOptions=%d, containerId=%d)", mainType, recvOptions, containerId);
|
||||
sceNp.warning("sceNpBasicRecvMessageCustom(mainType=%d, recvOptions=%d, containerId=%d)", mainType, recvOptions, containerId);
|
||||
|
||||
auto& nph = g_fxo->get<named_thread<np_handler>>();
|
||||
|
||||
@ -880,11 +1025,66 @@ error_code sceNpBasicRecvMessageCustom(u16 mainType, u32 recvOptions, sys_memory
|
||||
return SCE_NP_BASIC_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
if (!(recvOptions & SCE_NP_BASIC_RECV_MESSAGE_OPTIONS_ALL_OPTIONS))
|
||||
if (!nph.basic_handler.registered)
|
||||
{
|
||||
return SCE_NP_BASIC_ERROR_NOT_REGISTERED;
|
||||
}
|
||||
|
||||
if ((recvOptions & ~SCE_NP_BASIC_RECV_MESSAGE_OPTIONS_ALL_OPTIONS))
|
||||
{
|
||||
return SCE_NP_BASIC_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
// TODO: SCE_NP_BASIC_ERROR_NOT_SUPPORTED
|
||||
|
||||
atomic_t<bool> wake_up = false;
|
||||
bool result = false;
|
||||
|
||||
input::SetIntercepted(true);
|
||||
|
||||
SceNpBasicMessageRecvAction recv_result;
|
||||
u64 chosen_msg_id;
|
||||
|
||||
Emu.CallAfter([=, &wake_up, &result, &recv_result, &chosen_msg_id]()
|
||||
{
|
||||
auto recv_dlg = Emu.GetCallbacks().get_recvmessage_dialog();
|
||||
result = recv_dlg->Exec(static_cast<SceNpBasicMessageMainType>(mainType), static_cast<SceNpBasicMessageRecvOptions>(recvOptions), recv_result, chosen_msg_id);
|
||||
wake_up = true;
|
||||
wake_up.notify_one();
|
||||
});
|
||||
|
||||
while (!wake_up && !Emu.IsStopped())
|
||||
{
|
||||
thread_ctrl::wait_on(wake_up, false);
|
||||
}
|
||||
|
||||
input::SetIntercepted(false);
|
||||
|
||||
if (!result)
|
||||
{
|
||||
return SCE_NP_BASIC_ERROR_CANCEL;
|
||||
}
|
||||
|
||||
const auto msg_pair = nph.get_message(chosen_msg_id).value();
|
||||
const auto& msg = msg_pair->second;
|
||||
|
||||
const u32 event_to_send = (mainType == SCE_NP_BASIC_MESSAGE_MAIN_TYPE_INVITE) ? SCE_NP_BASIC_EVENT_RECV_INVITATION_RESULT : SCE_NP_BASIC_EVENT_RECV_CUSTOM_DATA_RESULT;
|
||||
np_handler::basic_event to_add{};
|
||||
to_add.event = event_to_send;
|
||||
strcpy_trunc(to_add.from.userId.handle.data, msg_pair->first);
|
||||
strcpy_trunc(to_add.from.name.data, msg_pair->first);
|
||||
to_add.data.resize(sizeof(SceNpBasicExtendedAttachmentData));
|
||||
SceNpBasicExtendedAttachmentData* att_data = reinterpret_cast<SceNpBasicExtendedAttachmentData*>(to_add.data.data());
|
||||
att_data->flags = 0; // ?
|
||||
att_data->msgId = chosen_msg_id;
|
||||
att_data->data.id = static_cast<u32>(chosen_msg_id);
|
||||
att_data->data.size = static_cast<u32>(msg.data.size());
|
||||
att_data->userAction = recv_result;
|
||||
att_data->markedAsUsed = (recvOptions & SCE_NP_BASIC_RECV_MESSAGE_OPTIONS_PRESERVE) ? 0 : 1;
|
||||
|
||||
nph.queue_basic_event(to_add);
|
||||
nph.send_basic_event(event_to_send, 0, 0);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@ -972,8 +1172,7 @@ error_code sceNpBasicGetFriendListEntryCount(vm::ptr<u32> count)
|
||||
return SCE_NP_ERROR_ID_NOT_FOUND;
|
||||
}
|
||||
|
||||
// TODO: Check if there are any friends
|
||||
*count = 0;
|
||||
*count = nph.get_num_friends();
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -1258,7 +1457,7 @@ error_code sceNpBasicGetBlockListEntryCount(vm::ptr<u32> count)
|
||||
}
|
||||
|
||||
// TODO: Check if there are block lists
|
||||
*count = 0;
|
||||
*count = nph.get_num_blocks();
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -1560,15 +1759,19 @@ error_code sceNpBasicGetEvent(vm::ptr<s32> event, vm::ptr<SceNpUserInfo> from, v
|
||||
return SCE_NP_BASIC_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
if (!nph.basic_handler.registered)
|
||||
{
|
||||
return SCE_NP_BASIC_ERROR_NOT_REGISTERED;
|
||||
}
|
||||
|
||||
if (!event || !from || !data || !size)
|
||||
{
|
||||
return SCE_NP_BASIC_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
// TODO: Check for other error and pass other events
|
||||
//*event = SCE_NP_BASIC_EVENT_OFFLINE; // This event only indicates a contact is offline, not the current status of the connection
|
||||
|
||||
return not_an_error(SCE_NP_BASIC_ERROR_NO_EVENT);
|
||||
return nph.get_basic_event(event, from, data, size);
|
||||
}
|
||||
|
||||
error_code sceNpCommerceCreateCtx(u32 version, vm::ptr<SceNpId> npId, vm::ptr<SceNpCommerceHandler> handler, vm::ptr<void> arg, vm::ptr<u32> ctx_id)
|
||||
@ -2913,10 +3116,10 @@ error_code sceNpManagerGetTicket(vm::ptr<void> buffer, vm::ptr<u32> bufferSize)
|
||||
}
|
||||
|
||||
const auto& ticket = nph.get_ticket();
|
||||
*bufferSize = static_cast<u32>(ticket.size());
|
||||
|
||||
if (!buffer)
|
||||
{
|
||||
*bufferSize = static_cast<u32>(ticket.size());
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,8 @@
|
||||
#include "cellRtc.h"
|
||||
#include "Emu/Cell/ErrorCodes.h"
|
||||
|
||||
#include <set>
|
||||
|
||||
error_code sceNpInit(u32 poolsize, vm::ptr<void> poolptr);
|
||||
error_code sceNpTerm();
|
||||
|
||||
@ -1022,11 +1024,11 @@ struct SceNpBasicMessageDetails
|
||||
be_t<u16> mainType;
|
||||
be_t<u16> subType;
|
||||
be_t<u32> msgFeatures;
|
||||
const SceNpId npids;
|
||||
vm::bptr<SceNpId> npids;
|
||||
be_t<u32> count;
|
||||
const s8 subject;
|
||||
const s8 body;
|
||||
const be_t<u32> data;
|
||||
vm::bptr<char> subject;
|
||||
vm::bptr<char> body;
|
||||
vm::bptr<u8> data;
|
||||
be_t<u32> size;
|
||||
};
|
||||
|
||||
@ -1359,3 +1361,33 @@ using SceNpMatchingGUIHandler = void(u32 ctx_id, s32 event, s32 error_code, vm::
|
||||
using SceNpProfileResultHandler = s32(s32 result, vm::ptr<void> arg);
|
||||
|
||||
using SceNpManagerSubSigninCallback = void(s32 result, vm::ptr<SceNpId> npId, vm::ptr<void> cb_arg);
|
||||
|
||||
// Used to pass data to UI/RPCN
|
||||
struct message_data
|
||||
{
|
||||
SceNpCommunicationId commId{};
|
||||
u64 msgId = 0;
|
||||
u16 mainType = 0;
|
||||
u16 subType = 0;
|
||||
u32 msgFeatures = 0;
|
||||
std::string subject;
|
||||
std::string body;
|
||||
std::vector<u8> data;
|
||||
void print() const;
|
||||
};
|
||||
|
||||
class SendMessageDialogBase
|
||||
{
|
||||
public:
|
||||
virtual ~SendMessageDialogBase() = default;
|
||||
|
||||
virtual bool Exec(message_data& msg_data, std::set<std::string>& npids) = 0;
|
||||
};
|
||||
|
||||
class RecvMessageDialogBase
|
||||
{
|
||||
public:
|
||||
virtual ~RecvMessageDialogBase() = default;
|
||||
|
||||
virtual bool Exec(SceNpBasicMessageMainType type, SceNpBasicMessageRecvOptions options, SceNpBasicMessageRecvAction& recv_result, u64& chosen_msg_id) = 0;
|
||||
};
|
||||
|
@ -613,17 +613,23 @@ error_code sceNpMatching2SignalingGetConnectionInfo(
|
||||
|
||||
switch (code)
|
||||
{
|
||||
case 1:
|
||||
case SCE_NP_SIGNALING_CONN_INFO_RTT:
|
||||
{
|
||||
connInfo->rtt = 20000; // HACK
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
case SCE_NP_SIGNALING_CONN_INFO_BANDWIDTH:
|
||||
{
|
||||
connInfo->bandwidth = 10'000'000; // 10 MBPS HACK
|
||||
break;
|
||||
}
|
||||
case 5:
|
||||
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");
|
||||
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);
|
||||
@ -631,7 +637,15 @@ error_code sceNpMatching2SignalingGetConnectionInfo(
|
||||
connInfo->address.addr.np_s_addr = si.addr;
|
||||
break;
|
||||
}
|
||||
case 6:
|
||||
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;
|
||||
}
|
||||
case SCE_NP_SIGNALING_CONN_INFO_PACKET_LOSS:
|
||||
{
|
||||
connInfo->packet_loss = 1; // HACK
|
||||
break;
|
||||
@ -1274,6 +1288,8 @@ error_code sceNpMatching2GetRoomDataExternalList(
|
||||
return res;
|
||||
}
|
||||
|
||||
*assignedReqId = nph.get_roomdata_external_list(ctxId, optParam, reqParam.get_ptr());
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -978,7 +978,7 @@ struct network_thread
|
||||
WSADATA wsa_data;
|
||||
WSAStartup(MAKEWORD(2, 2), &wsa_data);
|
||||
#endif
|
||||
if (g_cfg.net.psn_status == np_psn_status::rpcn)
|
||||
if (g_cfg.net.psn_status == np_psn_status::psn_rpcn)
|
||||
list_p2p_ports.emplace(std::piecewise_construct, std::forward_as_tuple(3658), std::forward_as_tuple(3658));
|
||||
}
|
||||
|
||||
|
@ -55,7 +55,68 @@ void np_handler::UserInfo2_to_SceNpUserInfo2(const UserInfo2* user, SceNpUserInf
|
||||
}
|
||||
}
|
||||
|
||||
void np_handler::SearchRoomReponse_to_SceNpMatching2SearchRoomResponse(const SearchRoomResponse* resp, SceNpMatching2SearchRoomResponse* search_resp)
|
||||
void np_handler::RoomDataExternal_to_SceNpMatching2RoomDataExternal(const RoomDataExternal* room, SceNpMatching2RoomDataExternal* room_info)
|
||||
{
|
||||
room_info->serverId = room->serverId();
|
||||
room_info->worldId = room->worldId();
|
||||
room_info->publicSlotNum = room->publicSlotNum();
|
||||
room_info->privateSlotNum = room->privateSlotNum();
|
||||
room_info->lobbyId = room->lobbyId();
|
||||
room_info->roomId = room->roomId();
|
||||
room_info->openPublicSlotNum = room->openPublicSlotNum();
|
||||
room_info->maxSlot = room->maxSlot();
|
||||
room_info->openPrivateSlotNum = room->openPrivateSlotNum();
|
||||
room_info->curMemberNum = room->curMemberNum();
|
||||
room_info->passwordSlotMask = room->passwordSlotMask();
|
||||
|
||||
if (auto owner = room->owner())
|
||||
{
|
||||
vm::ptr<SceNpUserInfo2> owner_info(allocate(sizeof(SceNpUserInfo2)));
|
||||
UserInfo2_to_SceNpUserInfo2(owner, owner_info.get_ptr());
|
||||
room_info->owner = owner_info;
|
||||
}
|
||||
|
||||
if (room->roomGroup() && room->roomGroup()->size() != 0)
|
||||
{
|
||||
room_info->roomGroupNum = room->roomGroup()->size();
|
||||
vm::ptr<SceNpMatching2RoomGroup> group_info(allocate(sizeof(SceNpMatching2RoomGroup) * room_info->roomGroupNum));
|
||||
RoomGroup_to_SceNpMatching2RoomGroup(room->roomGroup(), group_info);
|
||||
room_info->roomGroup = group_info;
|
||||
}
|
||||
|
||||
room_info->flagAttr = room->flagAttr();
|
||||
|
||||
if (room->roomSearchableIntAttrExternal() && room->roomSearchableIntAttrExternal()->size() != 0)
|
||||
{
|
||||
room_info->roomSearchableIntAttrExternalNum = room->roomSearchableIntAttrExternal()->size();
|
||||
vm::ptr<SceNpMatching2IntAttr> intattr_info(allocate(sizeof(SceNpMatching2IntAttr) * room_info->roomSearchableIntAttrExternalNum));
|
||||
for (flatbuffers::uoffset_t a_index = 0; a_index < room->roomSearchableIntAttrExternal()->size(); a_index++)
|
||||
{
|
||||
auto int_attr = room->roomSearchableIntAttrExternal()->Get(a_index);
|
||||
intattr_info[a_index].id = int_attr->id();
|
||||
intattr_info[a_index].num = int_attr->num();
|
||||
}
|
||||
room_info->roomSearchableIntAttrExternal = intattr_info;
|
||||
}
|
||||
|
||||
if (room->roomSearchableBinAttrExternal() && room->roomSearchableBinAttrExternal()->size() != 0)
|
||||
{
|
||||
room_info->roomSearchableBinAttrExternalNum = room->roomSearchableBinAttrExternal()->size();
|
||||
vm::ptr<SceNpMatching2BinAttr> binattr_info(allocate(sizeof(SceNpMatching2BinAttr) * room_info->roomSearchableBinAttrExternalNum));
|
||||
BinAttr_to_SceNpMatching2BinAttr(room->roomSearchableBinAttrExternal(), binattr_info);
|
||||
room_info->roomSearchableBinAttrExternal = binattr_info;
|
||||
}
|
||||
|
||||
if (room->roomBinAttrExternal() && room->roomBinAttrExternal()->size() != 0)
|
||||
{
|
||||
room_info->roomBinAttrExternalNum = room->roomBinAttrExternal()->size();
|
||||
vm::ptr<SceNpMatching2BinAttr> binattr_info(allocate(sizeof(SceNpMatching2BinAttr) * room_info->roomBinAttrExternalNum));
|
||||
BinAttr_to_SceNpMatching2BinAttr(room->roomBinAttrExternal(), binattr_info);
|
||||
room_info->roomBinAttrExternal = binattr_info;
|
||||
}
|
||||
}
|
||||
|
||||
void np_handler::SearchRoomResponse_to_SceNpMatching2SearchRoomResponse(const SearchRoomResponse* resp, SceNpMatching2SearchRoomResponse* search_resp)
|
||||
{
|
||||
search_resp->range.size = resp->size();
|
||||
search_resp->range.startIndex = resp->startIndex();
|
||||
@ -66,7 +127,7 @@ void np_handler::SearchRoomReponse_to_SceNpMatching2SearchRoomResponse(const Sea
|
||||
vm::addr_t previous_next = vm::cast<u32>(0);
|
||||
for (flatbuffers::uoffset_t i = 0; i < resp->rooms()->size(); i++)
|
||||
{
|
||||
auto room = resp->rooms()->Get(i);
|
||||
auto* room = resp->rooms()->Get(i);
|
||||
vm::ptr<SceNpMatching2RoomDataExternal> room_info(allocate(sizeof(SceNpMatching2RoomDataExternal)));
|
||||
|
||||
if (i > 0)
|
||||
@ -81,62 +142,7 @@ void np_handler::SearchRoomReponse_to_SceNpMatching2SearchRoomResponse(const Sea
|
||||
|
||||
previous_next = vm::cast(room_info.addr());
|
||||
|
||||
room_info->serverId = room->serverId();
|
||||
room_info->worldId = room->worldId();
|
||||
room_info->publicSlotNum = room->publicSlotNum();
|
||||
room_info->privateSlotNum = room->privateSlotNum();
|
||||
room_info->lobbyId = room->lobbyId();
|
||||
room_info->roomId = room->roomId();
|
||||
room_info->openPublicSlotNum = room->openPublicSlotNum();
|
||||
room_info->maxSlot = room->maxSlot();
|
||||
room_info->openPrivateSlotNum = room->openPrivateSlotNum();
|
||||
room_info->curMemberNum = room->curMemberNum();
|
||||
room_info->passwordSlotMask = room->curMemberNum();
|
||||
if (auto owner = room->owner())
|
||||
{
|
||||
vm::ptr<SceNpUserInfo2> owner_info(allocate(sizeof(SceNpUserInfo2)));
|
||||
UserInfo2_to_SceNpUserInfo2(owner, owner_info.get_ptr());
|
||||
room_info->owner = owner_info;
|
||||
}
|
||||
|
||||
if (room->roomGroup() && room->roomGroup()->size() != 0)
|
||||
{
|
||||
room_info->roomGroupNum = room->roomGroup()->size();
|
||||
vm::ptr<SceNpMatching2RoomGroup> group_info(allocate(sizeof(SceNpMatching2RoomGroup) * room_info->roomGroupNum));
|
||||
RoomGroup_to_SceNpMatching2RoomGroup(room->roomGroup(), group_info);
|
||||
room_info->roomGroup = group_info;
|
||||
}
|
||||
|
||||
room_info->flagAttr = room->flagAttr();
|
||||
|
||||
if (room->roomSearchableIntAttrExternal() && room->roomSearchableIntAttrExternal()->size() != 0)
|
||||
{
|
||||
room_info->roomSearchableIntAttrExternalNum = room->roomSearchableIntAttrExternal()->size();
|
||||
vm::ptr<SceNpMatching2IntAttr> intattr_info(allocate(sizeof(SceNpMatching2IntAttr) * room_info->roomSearchableIntAttrExternalNum));
|
||||
for (flatbuffers::uoffset_t a_index = 0; a_index < room->roomSearchableIntAttrExternal()->size(); a_index++)
|
||||
{
|
||||
auto int_attr = room->roomSearchableIntAttrExternal()->Get(a_index);
|
||||
intattr_info[a_index].id = int_attr->id();
|
||||
intattr_info[a_index].num = int_attr->num();
|
||||
}
|
||||
room_info->roomSearchableIntAttrExternal = intattr_info;
|
||||
}
|
||||
|
||||
if (room->roomSearchableBinAttrExternal() && room->roomSearchableBinAttrExternal()->size() != 0)
|
||||
{
|
||||
room_info->roomSearchableBinAttrExternalNum = room->roomSearchableBinAttrExternal()->size();
|
||||
vm::ptr<SceNpMatching2BinAttr> binattr_info(allocate(sizeof(SceNpMatching2BinAttr) * room_info->roomSearchableBinAttrExternalNum));
|
||||
BinAttr_to_SceNpMatching2BinAttr(room->roomSearchableBinAttrExternal(), binattr_info);
|
||||
room_info->roomSearchableBinAttrExternal = binattr_info;
|
||||
}
|
||||
|
||||
if (room->roomBinAttrExternal() && room->roomBinAttrExternal()->size() != 0)
|
||||
{
|
||||
room_info->roomBinAttrExternalNum = room->roomBinAttrExternal()->size();
|
||||
vm::ptr<SceNpMatching2BinAttr> binattr_info(allocate(sizeof(SceNpMatching2BinAttr) * room_info->roomBinAttrExternalNum));
|
||||
BinAttr_to_SceNpMatching2BinAttr(room->roomBinAttrExternal(), binattr_info);
|
||||
room_info->roomBinAttrExternal = binattr_info;
|
||||
}
|
||||
RoomDataExternal_to_SceNpMatching2RoomDataExternal(room, room_info.get_ptr());
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -145,6 +151,33 @@ void np_handler::SearchRoomReponse_to_SceNpMatching2SearchRoomResponse(const Sea
|
||||
}
|
||||
}
|
||||
|
||||
void np_handler::GetRoomDataExternalListResponse_to_SceNpMatching2GetRoomDataExternalListResponse(const GetRoomDataExternalListResponse* resp, SceNpMatching2GetRoomDataExternalListResponse* get_resp)
|
||||
{
|
||||
get_resp->roomDataExternalNum = resp->rooms() ? resp->rooms()->size() : 0;
|
||||
get_resp->roomDataExternal.set(0);
|
||||
|
||||
vm::addr_t previous_next = vm::cast<u32>(0);
|
||||
for (std::size_t i = 0; i < get_resp->roomDataExternalNum; i++)
|
||||
{
|
||||
auto* room = resp->rooms()->Get(i);
|
||||
vm::ptr<SceNpMatching2RoomDataExternal> room_info(allocate(sizeof(SceNpMatching2RoomDataExternal)));
|
||||
|
||||
if (i > 0)
|
||||
{
|
||||
vm::ptr<SceNpMatching2RoomDataExternal> prev_room(previous_next);
|
||||
prev_room->next.set(room_info.addr());
|
||||
}
|
||||
else
|
||||
{
|
||||
get_resp->roomDataExternal = room_info;
|
||||
}
|
||||
|
||||
previous_next = vm::cast(room_info.addr());
|
||||
|
||||
RoomDataExternal_to_SceNpMatching2RoomDataExternal(room, room_info.get_ptr());
|
||||
}
|
||||
}
|
||||
|
||||
u16 np_handler::RoomDataInternal_to_SceNpMatching2RoomDataInternal(const RoomDataInternal* resp, SceNpMatching2RoomDataInternal* room_info, const SceNpId& npid)
|
||||
{
|
||||
u16 member_id = 0;
|
||||
|
@ -167,6 +167,15 @@ table LeaveRoomRequest {
|
||||
optData:PresenceOptionData;
|
||||
}
|
||||
|
||||
table GetRoomDataExternalListRequest {
|
||||
roomIds:[uint64];
|
||||
attrIds:[uint16];
|
||||
}
|
||||
|
||||
table GetRoomDataExternalListResponse {
|
||||
rooms:[RoomDataExternal];
|
||||
}
|
||||
|
||||
table SetRoomDataExternalRequest {
|
||||
roomId:uint64;
|
||||
roomSearchableIntAttrExternal:[IntAttr];
|
||||
@ -223,3 +232,19 @@ table RoomMessageInfo {
|
||||
srcMember:UserInfo2;
|
||||
msg:[uint8];
|
||||
}
|
||||
|
||||
table MessageDetails {
|
||||
communicationId:string;
|
||||
msgId:uint64;
|
||||
mainType:uint16;
|
||||
subType:uint16;
|
||||
msgFeatures:uint32;
|
||||
subject:string;
|
||||
body:string;
|
||||
data:[uint8];
|
||||
}
|
||||
|
||||
table SendMessageRequest {
|
||||
message:[uint8] (nested_flatbuffer: "MessageDetails");
|
||||
npids:[string];
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -44,24 +44,25 @@ np_handler::np_handler()
|
||||
{
|
||||
g_fxo->need<named_thread<signaling_handler>>();
|
||||
|
||||
g_cfg_rpcn.load();
|
||||
std::lock_guard lock(mutex_rpcn);
|
||||
rpcn = rpcn::rpcn_client::get_instance();
|
||||
|
||||
is_connected = (g_cfg.net.net_active == np_internet_status::enabled);
|
||||
is_psn_active = (g_cfg.net.psn_status >= np_psn_status::fake);
|
||||
is_psn_active = (g_cfg.net.psn_status >= np_psn_status::psn_fake);
|
||||
|
||||
if (get_net_status() == CELL_NET_CTL_STATE_IPObtained)
|
||||
{
|
||||
if (!discover_ip_address())
|
||||
{
|
||||
nph_log.error("Failed to discover local IP!");
|
||||
is_connected = false;
|
||||
is_connected = false;
|
||||
is_psn_active = false;
|
||||
}
|
||||
|
||||
if (!discover_ether_address())
|
||||
{
|
||||
nph_log.error("Failed to discover ethernet address!");
|
||||
is_connected = false;
|
||||
is_connected = false;
|
||||
is_psn_active = false;
|
||||
}
|
||||
|
||||
@ -115,7 +116,7 @@ bool np_handler::discover_ip_address()
|
||||
|
||||
nph_log.notice("Hostname was determined to be %s", hostname.c_str());
|
||||
|
||||
hostent *host = gethostbyname(hostname.data());
|
||||
hostent* host = gethostbyname(hostname.data());
|
||||
if (!host)
|
||||
{
|
||||
nph_log.error("gethostbyname failed in IP discovery!");
|
||||
@ -129,7 +130,7 @@ bool np_handler::discover_ip_address()
|
||||
}
|
||||
|
||||
// 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]);
|
||||
local_ip_addr = *reinterpret_cast<u32*>(host->h_addr_list[0]);
|
||||
|
||||
// Set public address to local discovered address for now, may be updated later;
|
||||
public_ip_addr = local_ip_addr;
|
||||
@ -164,10 +165,10 @@ bool np_handler::discover_ether_address()
|
||||
std::vector<u8> adapter_infos(sizeof(IP_ADAPTER_INFO));
|
||||
ULONG size_infos = sizeof(IP_ADAPTER_INFO);
|
||||
|
||||
if (GetAdaptersInfo(reinterpret_cast<PIP_ADAPTER_INFO>(adapter_infos.data()), &size_infos) == ERROR_BUFFER_OVERFLOW)
|
||||
if (GetAdaptersInfo(reinterpret_cast<PIP_ADAPTER_INFO>(adapter_infos.data()), &size_infos) == ERROR_BUFFER_OVERFLOW)
|
||||
adapter_infos.resize(size_infos);
|
||||
|
||||
if (GetAdaptersInfo(reinterpret_cast<PIP_ADAPTER_INFO>(adapter_infos.data()), &size_infos) == NO_ERROR && size_infos)
|
||||
if (GetAdaptersInfo(reinterpret_cast<PIP_ADAPTER_INFO>(adapter_infos.data()), &size_infos) == NO_ERROR && size_infos)
|
||||
{
|
||||
PIP_ADAPTER_INFO info = reinterpret_cast<PIP_ADAPTER_INFO>(adapter_infos.data());
|
||||
memcpy(ether_address.data(), info[0].Address, 6);
|
||||
@ -305,6 +306,11 @@ void np_handler::string_to_avatar_url(const std::string& str, SceNpAvatarUrl* av
|
||||
strcpy_trunc(avatar_url->data, str);
|
||||
}
|
||||
|
||||
void np_handler::string_to_communication_id(const std::string& str, SceNpCommunicationId* comm_id)
|
||||
{
|
||||
strcpy_trunc(comm_id->data, str);
|
||||
}
|
||||
|
||||
void np_handler::init_NP(u32 poolsize, vm::ptr<void> poolptr)
|
||||
{
|
||||
// Init memory pool
|
||||
@ -317,7 +323,7 @@ void np_handler::init_NP(u32 poolsize, vm::ptr<void> poolptr)
|
||||
memset(&online_name, 0, sizeof(online_name));
|
||||
memset(&avatar_url, 0, sizeof(avatar_url));
|
||||
|
||||
if (g_cfg.net.psn_status >= np_psn_status::fake)
|
||||
if (g_cfg.net.psn_status >= np_psn_status::psn_fake)
|
||||
{
|
||||
std::string s_npid = g_cfg_rpcn.get_npid();
|
||||
ensure(!s_npid.empty()); // It should have been generated before this
|
||||
@ -331,35 +337,39 @@ void np_handler::init_NP(u32 poolsize, vm::ptr<void> poolptr)
|
||||
{
|
||||
case np_psn_status::disabled:
|
||||
break;
|
||||
case np_psn_status::fake:
|
||||
case np_psn_status::psn_fake:
|
||||
{
|
||||
np_handler::string_to_online_name("RPCS3's user", &online_name);
|
||||
np_handler::string_to_avatar_url("https://rpcs3.net/cdn/netplay/DefaultAvatar.png", &avatar_url);
|
||||
break;
|
||||
}
|
||||
case np_psn_status::rpcn:
|
||||
case np_psn_status::psn_rpcn:
|
||||
{
|
||||
if (!is_psn_active)
|
||||
break;
|
||||
|
||||
// Connect RPCN client
|
||||
if (!rpcn.connect(g_cfg_rpcn.get_host()))
|
||||
std::lock_guard lock(mutex_rpcn);
|
||||
rpcn = rpcn::rpcn_client::get_instance();
|
||||
|
||||
// Make sure we're connected
|
||||
|
||||
if (auto state = rpcn->wait_for_connection(); state != rpcn::rpcn_state::failure_no_failure)
|
||||
{
|
||||
rpcn_log.error("Connection to RPCN Failed!");
|
||||
is_psn_active = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!rpcn.login(g_cfg_rpcn.get_npid(), g_cfg_rpcn.get_password(), g_cfg_rpcn.get_token()))
|
||||
if (auto state = rpcn->wait_for_authentified(); state != rpcn::rpcn_state::failure_no_failure)
|
||||
{
|
||||
rpcn_log.error("RPCN login attempt failed!");
|
||||
is_psn_active = false;
|
||||
return;
|
||||
}
|
||||
|
||||
np_handler::string_to_online_name(rpcn.get_online_name(), &online_name);
|
||||
np_handler::string_to_avatar_url(rpcn.get_avatar_url(), &avatar_url);
|
||||
public_ip_addr = rpcn.get_addr_sig();
|
||||
np_handler::string_to_online_name(rpcn->get_online_name(), &online_name);
|
||||
np_handler::string_to_avatar_url(rpcn->get_avatar_url(), &avatar_url);
|
||||
public_ip_addr = rpcn->get_addr_sig();
|
||||
|
||||
break;
|
||||
}
|
||||
@ -376,10 +386,11 @@ void np_handler::terminate_NP()
|
||||
mpool_avail = 0;
|
||||
mpool_allocs.clear();
|
||||
|
||||
if (g_cfg.net.psn_status == np_psn_status::rpcn)
|
||||
if (g_cfg.net.psn_status == np_psn_status::psn_rpcn)
|
||||
{
|
||||
rpcn_log.error("Disconnecting from RPCN!");
|
||||
rpcn.disconnect();
|
||||
rpcn_log.notice("Disconnecting from RPCN!");
|
||||
std::lock_guard lock(mutex_rpcn);
|
||||
rpcn.reset();
|
||||
}
|
||||
}
|
||||
|
||||
@ -433,12 +444,12 @@ std::vector<SceNpMatching2ServerId> np_handler::get_match2_server_list(SceNpMatc
|
||||
{
|
||||
std::vector<SceNpMatching2ServerId> server_list{};
|
||||
|
||||
if (g_cfg.net.psn_status != np_psn_status::rpcn)
|
||||
if (g_cfg.net.psn_status != np_psn_status::psn_rpcn)
|
||||
{
|
||||
return server_list;
|
||||
}
|
||||
|
||||
if (!rpcn.get_server_list(get_req_id(0), get_match2_context(ctx_id)->communicationId, server_list))
|
||||
if (!rpcn->get_server_list(get_req_id(0), get_match2_context(ctx_id)->communicationId, server_list))
|
||||
{
|
||||
rpcn_log.error("Disconnecting from RPCN!");
|
||||
is_psn_active = false;
|
||||
@ -457,14 +468,13 @@ u32 np_handler::get_server_status(SceNpMatching2ContextId ctx_id, vm::cptr<SceNp
|
||||
serv_info->server.serverId = server_id;
|
||||
serv_info->server.status = SCE_NP_MATCHING2_SERVER_STATUS_AVAILABLE;
|
||||
|
||||
const auto cb_info = std::move(pending_requests.at(req_id));
|
||||
pending_requests.erase(req_id);
|
||||
const auto cb_info = take_pending_request(req_id);
|
||||
|
||||
sysutil_register_cb([=](ppu_thread& cb_ppu) -> s32
|
||||
{
|
||||
cb_info.cb(cb_ppu, cb_info.ctx_id, req_id, SCE_NP_MATCHING2_REQUEST_EVENT_GetServerInfo, event_key, 0, sizeof(SceNpMatching2GetServerInfoResponse), cb_info.cb_arg);
|
||||
return 0;
|
||||
});
|
||||
{
|
||||
cb_info.cb(cb_ppu, cb_info.ctx_id, req_id, SCE_NP_MATCHING2_REQUEST_EVENT_GetServerInfo, event_key, 0, sizeof(SceNpMatching2GetServerInfoResponse), cb_info.cb_arg);
|
||||
return 0;
|
||||
});
|
||||
|
||||
return req_id;
|
||||
}
|
||||
@ -474,14 +484,13 @@ u32 np_handler::create_server_context(SceNpMatching2ContextId ctx_id, vm::cptr<S
|
||||
u32 req_id = generate_callback_info(ctx_id, optParam);
|
||||
u32 event_key = get_event_key();
|
||||
|
||||
const auto cb_info = std::move(pending_requests.at(req_id));
|
||||
pending_requests.erase(req_id);
|
||||
const auto cb_info = take_pending_request(req_id);
|
||||
|
||||
sysutil_register_cb([=](ppu_thread& cb_ppu) -> s32
|
||||
{
|
||||
cb_info.cb(cb_ppu, cb_info.ctx_id, req_id, SCE_NP_MATCHING2_REQUEST_EVENT_CreateServerContext, event_key, 0, 0, cb_info.cb_arg);
|
||||
return 0;
|
||||
});
|
||||
{
|
||||
cb_info.cb(cb_ppu, cb_info.ctx_id, req_id, SCE_NP_MATCHING2_REQUEST_EVENT_CreateServerContext, event_key, 0, 0, cb_info.cb_arg);
|
||||
return 0;
|
||||
});
|
||||
|
||||
return req_id;
|
||||
}
|
||||
@ -490,7 +499,7 @@ u32 np_handler::get_world_list(SceNpMatching2ContextId ctx_id, vm::cptr<SceNpMat
|
||||
{
|
||||
u32 req_id = generate_callback_info(ctx_id, optParam);
|
||||
|
||||
if (!rpcn.get_world_list(req_id, get_match2_context(ctx_id)->communicationId, server_id))
|
||||
if (!rpcn->get_world_list(req_id, get_match2_context(ctx_id)->communicationId, server_id))
|
||||
{
|
||||
rpcn_log.error("Disconnecting from RPCN!");
|
||||
is_psn_active = false;
|
||||
@ -503,7 +512,7 @@ u32 np_handler::create_join_room(SceNpMatching2ContextId ctx_id, vm::cptr<SceNpM
|
||||
{
|
||||
u32 req_id = generate_callback_info(ctx_id, optParam);
|
||||
|
||||
if (!rpcn.createjoin_room(req_id, get_match2_context(ctx_id)->communicationId, req))
|
||||
if (!rpcn->createjoin_room(req_id, get_match2_context(ctx_id)->communicationId, req))
|
||||
{
|
||||
rpcn_log.error("Disconnecting from RPCN!");
|
||||
is_psn_active = false;
|
||||
@ -516,7 +525,7 @@ u32 np_handler::join_room(SceNpMatching2ContextId ctx_id, vm::cptr<SceNpMatching
|
||||
{
|
||||
u32 req_id = generate_callback_info(ctx_id, optParam);
|
||||
|
||||
if (!rpcn.join_room(req_id, get_match2_context(ctx_id)->communicationId, req))
|
||||
if (!rpcn->join_room(req_id, get_match2_context(ctx_id)->communicationId, req))
|
||||
{
|
||||
rpcn_log.error("Disconnecting from RPCN!");
|
||||
is_psn_active = false;
|
||||
@ -529,7 +538,7 @@ u32 np_handler::leave_room(SceNpMatching2ContextId ctx_id, vm::cptr<SceNpMatchin
|
||||
{
|
||||
u32 req_id = generate_callback_info(ctx_id, optParam);
|
||||
|
||||
if (!rpcn.leave_room(req_id, get_match2_context(ctx_id)->communicationId, req))
|
||||
if (!rpcn->leave_room(req_id, get_match2_context(ctx_id)->communicationId, req))
|
||||
{
|
||||
rpcn_log.error("Disconnecting from RPCN!");
|
||||
is_psn_active = false;
|
||||
@ -542,7 +551,20 @@ u32 np_handler::search_room(SceNpMatching2ContextId ctx_id, vm::cptr<SceNpMatchi
|
||||
{
|
||||
u32 req_id = generate_callback_info(ctx_id, optParam);
|
||||
|
||||
if (!rpcn.search_room(req_id, get_match2_context(ctx_id)->communicationId, req))
|
||||
if (!rpcn->search_room(req_id, get_match2_context(ctx_id)->communicationId, req))
|
||||
{
|
||||
rpcn_log.error("Disconnecting from RPCN!");
|
||||
is_psn_active = false;
|
||||
}
|
||||
|
||||
return req_id;
|
||||
}
|
||||
|
||||
u32 np_handler::get_roomdata_external_list(SceNpMatching2ContextId ctx_id, vm::cptr<SceNpMatching2RequestOptParam> optParam, const SceNpMatching2GetRoomDataExternalListRequest* req)
|
||||
{
|
||||
u32 req_id = generate_callback_info(ctx_id, optParam);
|
||||
|
||||
if (!rpcn->get_roomdata_external_list(req_id, get_match2_context(ctx_id)->communicationId, req))
|
||||
{
|
||||
rpcn_log.error("Disconnecting from RPCN!");
|
||||
is_psn_active = false;
|
||||
@ -557,7 +579,7 @@ u32 np_handler::set_roomdata_external(SceNpMatching2ContextId ctx_id, vm::cptr<S
|
||||
|
||||
extra_nps::print_set_roomdata_ext_req(req);
|
||||
|
||||
if (!rpcn.set_roomdata_external(req_id, get_match2_context(ctx_id)->communicationId, req))
|
||||
if (!rpcn->set_roomdata_external(req_id, get_match2_context(ctx_id)->communicationId, req))
|
||||
{
|
||||
rpcn_log.error("Disconnecting from RPCN!");
|
||||
is_psn_active = false;
|
||||
@ -570,7 +592,7 @@ u32 np_handler::get_roomdata_internal(SceNpMatching2ContextId ctx_id, vm::cptr<S
|
||||
{
|
||||
u32 req_id = generate_callback_info(ctx_id, optParam);
|
||||
|
||||
if (!rpcn.get_roomdata_internal(req_id, get_match2_context(ctx_id)->communicationId, req))
|
||||
if (!rpcn->get_roomdata_internal(req_id, get_match2_context(ctx_id)->communicationId, req))
|
||||
{
|
||||
rpcn_log.error("Disconnecting from RPCN!");
|
||||
is_psn_active = false;
|
||||
@ -585,7 +607,7 @@ u32 np_handler::set_roomdata_internal(SceNpMatching2ContextId ctx_id, vm::cptr<S
|
||||
|
||||
extra_nps::print_set_roomdata_int_req(req);
|
||||
|
||||
if (!rpcn.set_roomdata_internal(req_id, get_match2_context(ctx_id)->communicationId, req))
|
||||
if (!rpcn->set_roomdata_internal(req_id, get_match2_context(ctx_id)->communicationId, req))
|
||||
{
|
||||
rpcn_log.error("Disconnecting from RPCN!");
|
||||
is_psn_active = false;
|
||||
@ -598,7 +620,7 @@ u32 np_handler::get_ping_info(SceNpMatching2ContextId ctx_id, vm::cptr<SceNpMatc
|
||||
{
|
||||
u32 req_id = generate_callback_info(ctx_id, optParam);
|
||||
|
||||
if (!rpcn.ping_room_owner(req_id, get_match2_context(ctx_id)->communicationId, req->roomId))
|
||||
if (!rpcn->ping_room_owner(req_id, get_match2_context(ctx_id)->communicationId, req->roomId))
|
||||
{
|
||||
rpcn_log.error("Disconnecting from RPCN!");
|
||||
is_psn_active = false;
|
||||
@ -611,7 +633,7 @@ u32 np_handler::send_room_message(SceNpMatching2ContextId ctx_id, vm::cptr<SceNp
|
||||
{
|
||||
u32 req_id = generate_callback_info(ctx_id, optParam);
|
||||
|
||||
if (!rpcn.send_room_message(req_id, get_match2_context(ctx_id)->communicationId, req))
|
||||
if (!rpcn->send_room_message(req_id, get_match2_context(ctx_id)->communicationId, req))
|
||||
{
|
||||
rpcn_log.error("Disconnecting from RPCN!");
|
||||
is_psn_active = false;
|
||||
@ -623,9 +645,12 @@ u32 np_handler::send_room_message(SceNpMatching2ContextId ctx_id, vm::cptr<SceNp
|
||||
void np_handler::req_sign_infos(const std::string& npid, u32 conn_id)
|
||||
{
|
||||
u32 req_id = get_req_id(0x3333);
|
||||
pending_sign_infos_requests[req_id] = conn_id;
|
||||
{
|
||||
std::lock_guard lock(mutex_pending_sign_infos_requests);
|
||||
pending_sign_infos_requests[req_id] = conn_id;
|
||||
}
|
||||
|
||||
if (!rpcn.req_sign_infos(req_id, npid))
|
||||
if (!rpcn->req_sign_infos(req_id, npid))
|
||||
{
|
||||
rpcn_log.error("Disconnecting from RPCN!");
|
||||
is_psn_active = false;
|
||||
@ -640,7 +665,7 @@ void np_handler::req_ticket(u32 /*version*/, const SceNpId* /*npid*/, const char
|
||||
|
||||
std::string service_id_str(service_id);
|
||||
|
||||
if (!rpcn.req_ticket(req_id, service_id_str))
|
||||
if (!rpcn->req_ticket(req_id, service_id_str))
|
||||
{
|
||||
rpcn_log.error("Disconnecting from RPCN!");
|
||||
is_psn_active = false;
|
||||
@ -649,7 +674,6 @@ void np_handler::req_ticket(u32 /*version*/, const SceNpId* /*npid*/, const char
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
u32 np_handler::get_match2_event(SceNpMatching2EventKey event_key, u8* dest, u32 size)
|
||||
{
|
||||
std::lock_guard lock(mutex_req_results);
|
||||
@ -663,67 +687,181 @@ u32 np_handler::get_match2_event(SceNpMatching2EventKey event_key, u8* dest, u32
|
||||
return size_copied;
|
||||
}
|
||||
|
||||
bool np_handler::send_basic_event(s32 event, s32 retCode, u32 reqId)
|
||||
{
|
||||
if (basic_handler.registered)
|
||||
{
|
||||
sysutil_register_cb([handler_func = this->basic_handler.handler_func, handler_arg = this->basic_handler.handler_arg, event, retCode, reqId](ppu_thread& cb_ppu) -> s32
|
||||
{
|
||||
handler_func(cb_ppu, event, retCode, reqId, handler_arg);
|
||||
return 0;
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void np_handler::queue_basic_event(basic_event to_queue)
|
||||
{
|
||||
std::lock_guard lock(mutex_queue_basic_events);
|
||||
queue_basic_events.push(std::move(to_queue));
|
||||
}
|
||||
|
||||
error_code np_handler::get_basic_event(vm::ptr<s32> event, vm::ptr<SceNpUserInfo> from, vm::ptr<s32> data, vm::ptr<u32> size)
|
||||
{
|
||||
basic_event cur_event;
|
||||
{
|
||||
std::lock_guard lock(mutex_queue_basic_events);
|
||||
if (queue_basic_events.empty())
|
||||
{
|
||||
return not_an_error(SCE_NP_BASIC_ERROR_NO_EVENT);
|
||||
}
|
||||
|
||||
cur_event = std::move(queue_basic_events.front());
|
||||
queue_basic_events.pop();
|
||||
}
|
||||
|
||||
const u32 size_avail = *size;
|
||||
u32 res_size = std::min(static_cast<u32>(cur_event.data.size()), size_avail);
|
||||
|
||||
*event = cur_event.event;
|
||||
memcpy(from.get_ptr(), &cur_event.from, sizeof(cur_event.from));
|
||||
memcpy(data.get_ptr(), cur_event.data.data(), res_size);
|
||||
*size = res_size;
|
||||
|
||||
if (res_size < cur_event.data.size())
|
||||
{
|
||||
return SCE_NP_BASIC_ERROR_DATA_LOST;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
std::optional<std::shared_ptr<std::pair<std::string, message_data>>> np_handler::get_message(u64 id)
|
||||
{
|
||||
return rpcn->get_message(id);
|
||||
}
|
||||
|
||||
void np_handler::operator()()
|
||||
{
|
||||
if (g_cfg.net.psn_status != np_psn_status::rpcn)
|
||||
if (g_cfg.net.psn_status != np_psn_status::psn_rpcn)
|
||||
return;
|
||||
|
||||
while (thread_ctrl::state() != thread_state::aborting && !Emu.IsStopped())
|
||||
{
|
||||
if (!rpcn.manage_connection())
|
||||
bool sleep = true;
|
||||
if (rpcn)
|
||||
{
|
||||
std::lock_guard lock(mutex_rpcn);
|
||||
if (!rpcn)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
auto replies = rpcn->get_replies();
|
||||
for (auto& reply : replies)
|
||||
{
|
||||
const u16 command = reply.second.first;
|
||||
const u32 req_id = reply.first;
|
||||
std::vector<u8>& data = reply.second.second;
|
||||
|
||||
switch (command)
|
||||
{
|
||||
case rpcn::CommandType::GetWorldList: reply_get_world_list(req_id, data); break;
|
||||
case rpcn::CommandType::CreateRoom: reply_create_join_room(req_id, data); break;
|
||||
case rpcn::CommandType::JoinRoom: reply_join_room(req_id, data); break;
|
||||
case rpcn::CommandType::LeaveRoom: reply_leave_room(req_id, data); break;
|
||||
case rpcn::CommandType::SearchRoom: reply_search_room(req_id, data); break;
|
||||
case rpcn::CommandType::GetRoomDataExternalList: reply_get_roomdata_external_list(req_id, data); break;
|
||||
case rpcn::CommandType::SetRoomDataExternal: reply_set_roomdata_external(req_id, data); break;
|
||||
case rpcn::CommandType::GetRoomDataInternal: reply_get_roomdata_internal(req_id, data); break;
|
||||
case rpcn::CommandType::SetRoomDataInternal: reply_set_roomdata_internal(req_id, data); break;
|
||||
case rpcn::CommandType::PingRoomOwner: reply_get_ping_info(req_id, data); break;
|
||||
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;
|
||||
default: rpcn_log.error("Unknown reply(%d) received!", command); break;
|
||||
}
|
||||
}
|
||||
|
||||
auto notifications = rpcn->get_notifications();
|
||||
for (auto& notif : notifications)
|
||||
{
|
||||
switch (notif.first)
|
||||
{
|
||||
case rpcn::NotificationType::UserJoinedRoom: notif_user_joined_room(notif.second); break;
|
||||
case rpcn::NotificationType::UserLeftRoom: notif_user_left_room(notif.second); break;
|
||||
case rpcn::NotificationType::RoomDestroyed: notif_room_destroyed(notif.second); break;
|
||||
case rpcn::NotificationType::SignalP2PConnect: notif_p2p_connect(notif.second); break;
|
||||
case rpcn::NotificationType::RoomMessageReceived: notif_room_message_received(notif.second); break;
|
||||
default: rpcn_log.error("Unknown notification(%d) received!", notif.first); break;
|
||||
}
|
||||
}
|
||||
|
||||
auto messages = rpcn->get_new_messages();
|
||||
if (basic_handler.registered)
|
||||
{
|
||||
for (const auto msg_id : messages)
|
||||
{
|
||||
const auto opt_msg = rpcn->get_message(msg_id);
|
||||
if (!opt_msg)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const auto& msg = opt_msg.value();
|
||||
if (strncmp(msg->second.commId.data, basic_handler.context.data, sizeof(basic_handler.context.data) - 1) == 0)
|
||||
{
|
||||
u32 event;
|
||||
switch (msg->second.mainType)
|
||||
{
|
||||
case SCE_NP_BASIC_MESSAGE_MAIN_TYPE_DATA_ATTACHMENT:
|
||||
event = SCE_NP_BASIC_EVENT_INCOMING_ATTACHMENT;
|
||||
break;
|
||||
case SCE_NP_BASIC_MESSAGE_MAIN_TYPE_INVITE:
|
||||
event = (msg->second.msgFeatures & SCE_NP_BASIC_MESSAGE_FEATURES_BOOTABLE) ? SCE_NP_BASIC_EVENT_INCOMING_BOOTABLE_INVITATION : SCE_NP_BASIC_EVENT_INCOMING_INVITATION;
|
||||
break;
|
||||
case SCE_NP_BASIC_MESSAGE_MAIN_TYPE_CUSTOM_DATA:
|
||||
event = (msg->second.msgFeatures & SCE_NP_BASIC_MESSAGE_FEATURES_BOOTABLE) ? SCE_NP_BASIC_EVENT_INCOMING_BOOTABLE_CUSTOM_DATA_MESSAGE : SCE_NP_BASIC_EVENT_INCOMING_CUSTOM_DATA_MESSAGE;
|
||||
break;
|
||||
case SCE_NP_BASIC_MESSAGE_MAIN_TYPE_GENERAL:
|
||||
case SCE_NP_BASIC_MESSAGE_MAIN_TYPE_ADD_FRIEND:
|
||||
case SCE_NP_BASIC_MESSAGE_MAIN_TYPE_URL_ATTACHMENT:
|
||||
event = SCE_NP_BASIC_EVENT_MESSAGE;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
basic_event to_add{};
|
||||
to_add.event = event;
|
||||
strcpy_trunc(to_add.from.userId.handle.data, msg->first);
|
||||
strcpy_trunc(to_add.from.name.data, msg->first);
|
||||
|
||||
queue_basic_event(std::move(to_add));
|
||||
send_basic_event(event, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!replies.empty() || !notifications.empty())
|
||||
{
|
||||
sleep = false;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: replace with an appropriate semaphore
|
||||
if (sleep)
|
||||
{
|
||||
thread_ctrl::wait_for(200'000);
|
||||
continue;
|
||||
}
|
||||
|
||||
auto replies = rpcn.get_replies();
|
||||
for (auto& reply : replies)
|
||||
{
|
||||
const u16 command = reply.second.first;
|
||||
const u32 req_id = reply.first;
|
||||
std::vector<u8>& data = reply.second.second;
|
||||
|
||||
switch (command)
|
||||
{
|
||||
case CommandType::GetWorldList: reply_get_world_list(req_id, data); break;
|
||||
case CommandType::CreateRoom: reply_create_join_room(req_id, data); break;
|
||||
case CommandType::JoinRoom: reply_join_room(req_id, data); break;
|
||||
case CommandType::LeaveRoom: reply_leave_room(req_id, data); break;
|
||||
case CommandType::SearchRoom: reply_search_room(req_id, data); break;
|
||||
case CommandType::SetRoomDataExternal: reply_set_roomdata_external(req_id, data); break;
|
||||
case CommandType::GetRoomDataInternal: reply_get_roomdata_internal(req_id, data); break;
|
||||
case CommandType::SetRoomDataInternal: reply_set_roomdata_internal(req_id, data); break;
|
||||
case CommandType::PingRoomOwner: reply_get_ping_info(req_id, data); break;
|
||||
case CommandType::SendRoomMessage: reply_send_room_message(req_id, data); break;
|
||||
case CommandType::RequestSignalingInfos: reply_req_sign_infos(req_id, data); break;
|
||||
case CommandType::RequestTicket: reply_req_ticket(req_id, data); break;
|
||||
default: rpcn_log.error("Unknown reply(%d) received!", command); break;
|
||||
}
|
||||
}
|
||||
|
||||
auto notifications = rpcn.get_notifications();
|
||||
for (auto& notif : notifications)
|
||||
{
|
||||
switch (notif.first)
|
||||
{
|
||||
case NotificationType::UserJoinedRoom: notif_user_joined_room(notif.second); break;
|
||||
case NotificationType::UserLeftRoom: notif_user_left_room(notif.second); break;
|
||||
case NotificationType::RoomDestroyed: notif_room_destroyed(notif.second); break;
|
||||
case NotificationType::SignalP2PConnect: notif_p2p_connect(notif.second); break;
|
||||
case NotificationType::RoomMessageReceived: notif_room_message_received(notif.second); break;
|
||||
default: rpcn_log.error("Unknown notification(%d) received!", notif.first); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool np_handler::reply_get_world_list(u32 req_id, std::vector<u8>& reply_data)
|
||||
{
|
||||
if (pending_requests.count(req_id) == 0)
|
||||
return error_and_disconnect("Unexpected reply ID to GetWorldList");
|
||||
|
||||
const auto cb_info = std::move(pending_requests.at(req_id));
|
||||
pending_requests.erase(req_id);
|
||||
const auto cb_info = take_pending_request(req_id);
|
||||
|
||||
vec_stream reply(reply_data, 1);
|
||||
|
||||
@ -760,21 +898,17 @@ bool np_handler::reply_get_world_list(u32 req_id, std::vector<u8>& reply_data)
|
||||
}
|
||||
|
||||
sysutil_register_cb([=](ppu_thread& cb_ppu) -> s32
|
||||
{
|
||||
cb_info.cb(cb_ppu, cb_info.ctx_id, req_id, SCE_NP_MATCHING2_REQUEST_EVENT_GetWorldInfoList, event_key, 0, sizeof(SceNpMatching2GetWorldInfoListResponse), cb_info.cb_arg);
|
||||
return 0;
|
||||
});
|
||||
{
|
||||
cb_info.cb(cb_ppu, cb_info.ctx_id, req_id, SCE_NP_MATCHING2_REQUEST_EVENT_GetWorldInfoList, event_key, 0, sizeof(SceNpMatching2GetWorldInfoListResponse), cb_info.cb_arg);
|
||||
return 0;
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool np_handler::reply_create_join_room(u32 req_id, std::vector<u8>& reply_data)
|
||||
{
|
||||
if (pending_requests.count(req_id) == 0)
|
||||
return error_and_disconnect("Unexpected reply ID to CreateRoom");
|
||||
|
||||
const auto cb_info = std::move(pending_requests.at(req_id));
|
||||
pending_requests.erase(req_id);
|
||||
const auto cb_info = take_pending_request(req_id);
|
||||
|
||||
vec_stream reply(reply_data, 1);
|
||||
auto create_room_resp = reply.get_rawdata();
|
||||
@ -795,27 +929,23 @@ bool np_handler::reply_create_join_room(u32 req_id, std::vector<u8>& reply_data)
|
||||
// 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(), true);
|
||||
// TODO? Should this send a message to Signaling CB? Is this even necessary?
|
||||
|
||||
extra_nps::print_create_room_resp(room_resp);
|
||||
|
||||
sysutil_register_cb([=](ppu_thread& cb_ppu) -> s32
|
||||
{
|
||||
cb_info.cb(cb_ppu, cb_info.ctx_id, req_id, SCE_NP_MATCHING2_REQUEST_EVENT_CreateJoinRoom, event_key, 0, sizeof(SceNpMatching2CreateJoinRoomResponse), cb_info.cb_arg);
|
||||
return 0;
|
||||
});
|
||||
{
|
||||
cb_info.cb(cb_ppu, cb_info.ctx_id, req_id, SCE_NP_MATCHING2_REQUEST_EVENT_CreateJoinRoom, event_key, 0, sizeof(SceNpMatching2CreateJoinRoomResponse), cb_info.cb_arg);
|
||||
return 0;
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool np_handler::reply_join_room(u32 req_id, std::vector<u8>& reply_data)
|
||||
{
|
||||
if (pending_requests.count(req_id) == 0)
|
||||
return error_and_disconnect("Unexpected reply ID to JoinRoom");
|
||||
|
||||
const auto cb_info = std::move(pending_requests.at(req_id));
|
||||
pending_requests.erase(req_id);
|
||||
const auto cb_info = take_pending_request(req_id);
|
||||
|
||||
vec_stream reply(reply_data, 1);
|
||||
|
||||
@ -839,25 +969,21 @@ bool np_handler::reply_join_room(u32 req_id, std::vector<u8>& reply_data)
|
||||
// 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(), true);
|
||||
// TODO? Should this send a message to Signaling CB? Is this even necessary?
|
||||
|
||||
sysutil_register_cb([=](ppu_thread& cb_ppu) -> s32
|
||||
{
|
||||
cb_info.cb(cb_ppu, cb_info.ctx_id, req_id, SCE_NP_MATCHING2_REQUEST_EVENT_JoinRoom, event_key, 0, sizeof(SceNpMatching2JoinRoomResponse), cb_info.cb_arg);
|
||||
return 0;
|
||||
});
|
||||
{
|
||||
cb_info.cb(cb_ppu, cb_info.ctx_id, req_id, SCE_NP_MATCHING2_REQUEST_EVENT_JoinRoom, event_key, 0, sizeof(SceNpMatching2JoinRoomResponse), cb_info.cb_arg);
|
||||
return 0;
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool np_handler::reply_leave_room(u32 req_id, std::vector<u8>& reply_data)
|
||||
{
|
||||
if (pending_requests.count(req_id) == 0)
|
||||
return error_and_disconnect("Unexpected reply ID to LeaveRoom");
|
||||
|
||||
const auto cb_info = std::move(pending_requests.at(req_id));
|
||||
pending_requests.erase(req_id);
|
||||
const auto cb_info = take_pending_request(req_id);
|
||||
|
||||
vec_stream reply(reply_data, 1);
|
||||
u64 room_id = reply.get<u64>();
|
||||
@ -871,21 +997,17 @@ bool np_handler::reply_leave_room(u32 req_id, std::vector<u8>& reply_data)
|
||||
sigh.disconnect_sig2_users(room_id);
|
||||
|
||||
sysutil_register_cb([=](ppu_thread& cb_ppu) -> s32
|
||||
{
|
||||
cb_info.cb(cb_ppu, cb_info.ctx_id, req_id, SCE_NP_MATCHING2_REQUEST_EVENT_LeaveRoom, event_key, 0, 0, cb_info.cb_arg);
|
||||
return 0;
|
||||
});
|
||||
{
|
||||
cb_info.cb(cb_ppu, cb_info.ctx_id, req_id, SCE_NP_MATCHING2_REQUEST_EVENT_LeaveRoom, event_key, 0, 0, cb_info.cb_arg);
|
||||
return 0;
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool np_handler::reply_search_room(u32 req_id, std::vector<u8>& reply_data)
|
||||
{
|
||||
if (pending_requests.count(req_id) == 0)
|
||||
return error_and_disconnect("Unexpected reply ID to SearchRoom");
|
||||
|
||||
const auto cb_info = std::move(pending_requests.at(req_id));
|
||||
pending_requests.erase(req_id);
|
||||
const auto cb_info = take_pending_request(req_id);
|
||||
|
||||
vec_stream reply(reply_data, 1);
|
||||
auto search_room_resp = reply.get_rawdata();
|
||||
@ -897,43 +1019,60 @@ bool np_handler::reply_search_room(u32 req_id, std::vector<u8>& reply_data)
|
||||
auto resp = flatbuffers::GetRoot<SearchRoomResponse>(search_room_resp.data());
|
||||
SceNpMatching2SearchRoomResponse* search_resp = reinterpret_cast<SceNpMatching2SearchRoomResponse*>(allocate_req_result(event_key, sizeof(SceNpMatching2SearchRoomResponse)));
|
||||
|
||||
SearchRoomReponse_to_SceNpMatching2SearchRoomResponse(resp, search_resp);
|
||||
SearchRoomResponse_to_SceNpMatching2SearchRoomResponse(resp, search_resp);
|
||||
|
||||
sysutil_register_cb([=](ppu_thread& cb_ppu) -> s32
|
||||
{
|
||||
cb_info.cb(cb_ppu, cb_info.ctx_id, req_id, SCE_NP_MATCHING2_REQUEST_EVENT_SearchRoom, event_key, 0, sizeof(SceNpMatching2SearchRoomResponse), cb_info.cb_arg);
|
||||
return 0;
|
||||
});
|
||||
{
|
||||
cb_info.cb(cb_ppu, cb_info.ctx_id, req_id, SCE_NP_MATCHING2_REQUEST_EVENT_SearchRoom, event_key, 0, sizeof(SceNpMatching2SearchRoomResponse), cb_info.cb_arg);
|
||||
return 0;
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool np_handler::reply_get_roomdata_external_list(u32 req_id, std::vector<u8>& reply_data)
|
||||
{
|
||||
const auto cb_info = take_pending_request(req_id);
|
||||
|
||||
vec_stream reply(reply_data, 1);
|
||||
auto get_room_ext_resp = reply.get_rawdata();
|
||||
if (reply.is_error())
|
||||
return error_and_disconnect("Malformed reply to GetRoomDataExternalList command");
|
||||
|
||||
u32 event_key = get_event_key();
|
||||
|
||||
auto resp = flatbuffers::GetRoot<GetRoomDataExternalListResponse>(get_room_ext_resp.data());
|
||||
SceNpMatching2GetRoomDataExternalListResponse* np_get_room_ext_resp = reinterpret_cast<SceNpMatching2GetRoomDataExternalListResponse*>(allocate_req_result(event_key, sizeof(SceNpMatching2GetRoomDataExternalListResponse)));
|
||||
|
||||
GetRoomDataExternalListResponse_to_SceNpMatching2GetRoomDataExternalListResponse(resp, np_get_room_ext_resp);
|
||||
|
||||
sysutil_register_cb([=](ppu_thread& cb_ppu) -> s32
|
||||
{
|
||||
cb_info.cb(cb_ppu, cb_info.ctx_id, req_id, SCE_NP_MATCHING2_REQUEST_EVENT_SearchRoom, event_key, 0, sizeof(SceNpMatching2SearchRoomResponse), cb_info.cb_arg);
|
||||
return 0;
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool np_handler::reply_set_roomdata_external(u32 req_id, std::vector<u8>& /*reply_data*/)
|
||||
{
|
||||
if (pending_requests.count(req_id) == 0)
|
||||
return error_and_disconnect("Unexpected reply ID to SetRoomDataExternal");
|
||||
|
||||
const auto cb_info = std::move(pending_requests.at(req_id));
|
||||
pending_requests.erase(req_id);
|
||||
const auto cb_info = take_pending_request(req_id);
|
||||
|
||||
u32 event_key = get_event_key(); // Unsure if necessary if there is no data
|
||||
|
||||
sysutil_register_cb([=](ppu_thread& cb_ppu) -> s32
|
||||
{
|
||||
cb_info.cb(cb_ppu, cb_info.ctx_id, req_id, SCE_NP_MATCHING2_REQUEST_EVENT_SetRoomDataExternal, event_key, 0, 0, cb_info.cb_arg);
|
||||
return 0;
|
||||
});
|
||||
{
|
||||
cb_info.cb(cb_ppu, cb_info.ctx_id, req_id, SCE_NP_MATCHING2_REQUEST_EVENT_SetRoomDataExternal, event_key, 0, 0, cb_info.cb_arg);
|
||||
return 0;
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool np_handler::reply_get_roomdata_internal(u32 req_id, std::vector<u8>& reply_data)
|
||||
{
|
||||
if (pending_requests.count(req_id) == 0)
|
||||
return error_and_disconnect("Unexpected reply ID to GetRoomDataInternal");
|
||||
|
||||
const auto cb_info = std::move(pending_requests.at(req_id));
|
||||
pending_requests.erase(req_id);
|
||||
const auto cb_info = take_pending_request(req_id);
|
||||
|
||||
vec_stream reply(reply_data, 1);
|
||||
|
||||
@ -953,40 +1092,32 @@ bool np_handler::reply_get_roomdata_internal(u32 req_id, std::vector<u8>& reply_
|
||||
extra_nps::print_room_data_internal(room_resp->roomDataInternal.get_ptr());
|
||||
|
||||
sysutil_register_cb([=](ppu_thread& cb_ppu) -> s32
|
||||
{
|
||||
cb_info.cb(cb_ppu, cb_info.ctx_id, req_id, SCE_NP_MATCHING2_REQUEST_EVENT_GetRoomDataInternal, event_key, 0, sizeof(SceNpMatching2GetRoomDataInternalResponse), cb_info.cb_arg);
|
||||
return 0;
|
||||
});
|
||||
{
|
||||
cb_info.cb(cb_ppu, cb_info.ctx_id, req_id, SCE_NP_MATCHING2_REQUEST_EVENT_GetRoomDataInternal, event_key, 0, sizeof(SceNpMatching2GetRoomDataInternalResponse), cb_info.cb_arg);
|
||||
return 0;
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool np_handler::reply_set_roomdata_internal(u32 req_id, std::vector<u8>& /*reply_data*/)
|
||||
{
|
||||
if (pending_requests.count(req_id) == 0)
|
||||
return error_and_disconnect("Unexpected reply ID to SetRoomDataInternal");
|
||||
|
||||
const auto cb_info = std::move(pending_requests.at(req_id));
|
||||
pending_requests.erase(req_id);
|
||||
const auto cb_info = take_pending_request(req_id);
|
||||
|
||||
u32 event_key = get_event_key(); // Unsure if necessary if there is no data
|
||||
|
||||
sysutil_register_cb([=](ppu_thread& cb_ppu) -> s32
|
||||
{
|
||||
cb_info.cb(cb_ppu, cb_info.ctx_id, req_id, SCE_NP_MATCHING2_REQUEST_EVENT_SetRoomDataInternal, event_key, 0, 0, cb_info.cb_arg);
|
||||
return 0;
|
||||
});
|
||||
{
|
||||
cb_info.cb(cb_ppu, cb_info.ctx_id, req_id, SCE_NP_MATCHING2_REQUEST_EVENT_SetRoomDataInternal, event_key, 0, 0, cb_info.cb_arg);
|
||||
return 0;
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool np_handler::reply_get_ping_info(u32 req_id, std::vector<u8>& reply_data)
|
||||
{
|
||||
if (pending_requests.count(req_id) == 0)
|
||||
return error_and_disconnect("Unexpected reply ID to PingRoomOwner");
|
||||
|
||||
const auto cb_info = std::move(pending_requests.at(req_id));
|
||||
pending_requests.erase(req_id);
|
||||
const auto cb_info = take_pending_request(req_id);
|
||||
|
||||
vec_stream reply(reply_data, 1);
|
||||
|
||||
@ -1002,38 +1133,35 @@ bool np_handler::reply_get_ping_info(u32 req_id, std::vector<u8>& reply_data)
|
||||
GetPingInfoResponse_to_SceNpMatching2SignalingGetPingInfoResponse(resp, final_ping_resp);
|
||||
|
||||
sysutil_register_cb([=](ppu_thread& cb_ppu) -> s32
|
||||
{
|
||||
cb_info.cb(cb_ppu, cb_info.ctx_id, req_id, SCE_NP_MATCHING2_REQUEST_EVENT_SignalingGetPingInfo, event_key, 0, sizeof(SceNpMatching2SignalingGetPingInfoResponse), cb_info.cb_arg);
|
||||
return 0;
|
||||
});
|
||||
{
|
||||
cb_info.cb(cb_ppu, cb_info.ctx_id, req_id, SCE_NP_MATCHING2_REQUEST_EVENT_SignalingGetPingInfo, event_key, 0, sizeof(SceNpMatching2SignalingGetPingInfoResponse), cb_info.cb_arg);
|
||||
return 0;
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool np_handler::reply_send_room_message(u32 req_id, std::vector<u8>& /*reply_data*/)
|
||||
{
|
||||
if (pending_requests.count(req_id) == 0)
|
||||
return error_and_disconnect("Unexpected reply ID to PingRoomOwner");
|
||||
|
||||
const auto cb_info = std::move(pending_requests.at(req_id));
|
||||
pending_requests.erase(req_id);
|
||||
const auto cb_info = take_pending_request(req_id);
|
||||
|
||||
sysutil_register_cb([=](ppu_thread& cb_ppu) -> s32
|
||||
{
|
||||
cb_info.cb(cb_ppu, cb_info.ctx_id, req_id, SCE_NP_MATCHING2_REQUEST_EVENT_SendRoomMessage, 0, 0, 0, cb_info.cb_arg);
|
||||
return 0;
|
||||
});
|
||||
{
|
||||
cb_info.cb(cb_ppu, cb_info.ctx_id, req_id, SCE_NP_MATCHING2_REQUEST_EVENT_SendRoomMessage, 0, 0, 0, cb_info.cb_arg);
|
||||
return 0;
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool np_handler::reply_req_sign_infos(u32 req_id, std::vector<u8>& reply_data)
|
||||
{
|
||||
if (!pending_sign_infos_requests.count(req_id))
|
||||
return error_and_disconnect("Unexpected reply ID to req RequestSignalingInfos");
|
||||
|
||||
u32 conn_id = pending_sign_infos_requests.at(req_id);
|
||||
pending_sign_infos_requests.erase(req_id);
|
||||
u32 conn_id;
|
||||
{
|
||||
std::lock_guard lock(mutex_pending_sign_infos_requests);
|
||||
conn_id = pending_sign_infos_requests.at(req_id);
|
||||
pending_sign_infos_requests.erase(req_id);
|
||||
}
|
||||
|
||||
vec_stream reply(reply_data, 1);
|
||||
u32 addr = reply.get<u32>();
|
||||
@ -1056,16 +1184,16 @@ bool np_handler::reply_req_ticket(u32 /*req_id*/, std::vector<u8>& reply_data)
|
||||
if (reply.is_error())
|
||||
return error_and_disconnect("Malformed reply to RequestTicket command");
|
||||
|
||||
current_ticket = std::move(ticket_raw);
|
||||
current_ticket = std::move(ticket_raw);
|
||||
auto ticket_size = static_cast<s32>(current_ticket.size());
|
||||
|
||||
if (manager_cb)
|
||||
{
|
||||
sysutil_register_cb([manager_cb = this->manager_cb, ticket_size, manager_cb_arg = this->manager_cb_arg](ppu_thread& cb_ppu) -> s32
|
||||
{
|
||||
manager_cb(cb_ppu, SCE_NP_MANAGER_EVENT_GOT_TICKET, ticket_size, manager_cb_arg);
|
||||
return 0;
|
||||
});
|
||||
{
|
||||
manager_cb(cb_ppu, SCE_NP_MANAGER_EVENT_GOT_TICKET, ticket_size, manager_cb_arg);
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -1093,10 +1221,10 @@ void np_handler::notif_user_joined_room(std::vector<u8>& data)
|
||||
extra_nps::print_room_member_data_internal(notif_data->roomMemberDataInternal.get_ptr());
|
||||
|
||||
sysutil_register_cb([room_event_cb = this->room_event_cb, room_id, event_key, room_event_cb_ctx = this->room_event_cb_ctx, room_event_cb_arg = this->room_event_cb_arg](ppu_thread& cb_ppu) -> s32
|
||||
{
|
||||
room_event_cb(cb_ppu, room_event_cb_ctx, room_id, SCE_NP_MATCHING2_ROOM_EVENT_MemberJoined, event_key, 0, sizeof(SceNpMatching2RoomMemberUpdateInfo), room_event_cb_arg);
|
||||
return 0;
|
||||
});
|
||||
{
|
||||
room_event_cb(cb_ppu, room_event_cb_ctx, room_id, SCE_NP_MATCHING2_ROOM_EVENT_MemberJoined, event_key, 0, sizeof(SceNpMatching2RoomMemberUpdateInfo), room_event_cb_arg);
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
|
||||
void np_handler::notif_user_left_room(std::vector<u8>& data)
|
||||
@ -1121,10 +1249,10 @@ void np_handler::notif_user_left_room(std::vector<u8>& data)
|
||||
extra_nps::print_room_member_data_internal(notif_data->roomMemberDataInternal.get_ptr());
|
||||
|
||||
sysutil_register_cb([room_event_cb = this->room_event_cb, room_event_cb_ctx = this->room_event_cb_ctx, room_id, event_key, room_event_cb_arg = this->room_event_cb_arg](ppu_thread& cb_ppu) -> s32
|
||||
{
|
||||
room_event_cb(cb_ppu, room_event_cb_ctx, room_id, SCE_NP_MATCHING2_ROOM_EVENT_MemberLeft, event_key, 0, sizeof(SceNpMatching2RoomMemberUpdateInfo), room_event_cb_arg);
|
||||
return 0;
|
||||
});
|
||||
{
|
||||
room_event_cb(cb_ppu, room_event_cb_ctx, room_id, SCE_NP_MATCHING2_ROOM_EVENT_MemberLeft, event_key, 0, sizeof(SceNpMatching2RoomMemberUpdateInfo), room_event_cb_arg);
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
|
||||
void np_handler::notif_room_destroyed(std::vector<u8>& data)
|
||||
@ -1151,10 +1279,10 @@ void np_handler::notif_room_destroyed(std::vector<u8>& data)
|
||||
sigh.disconnect_sig2_users(room_id);
|
||||
|
||||
sysutil_register_cb([room_event_cb = this->room_event_cb, room_event_cb_ctx = this->room_event_cb_ctx, room_id, event_key, room_event_cb_arg = this->room_event_cb_arg](ppu_thread& cb_ppu) -> s32
|
||||
{
|
||||
room_event_cb(cb_ppu, room_event_cb_ctx, room_id, SCE_NP_MATCHING2_ROOM_EVENT_RoomDestroyed, event_key, 0, sizeof(SceNpMatching2RoomUpdateInfo), room_event_cb_arg);
|
||||
return 0;
|
||||
});
|
||||
{
|
||||
room_event_cb(cb_ppu, room_event_cb_ctx, room_id, SCE_NP_MATCHING2_ROOM_EVENT_RoomDestroyed, event_key, 0, sizeof(SceNpMatching2RoomUpdateInfo), room_event_cb_arg);
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
|
||||
void np_handler::notif_p2p_connect(std::vector<u8>& data)
|
||||
@ -1165,10 +1293,10 @@ void np_handler::notif_p2p_connect(std::vector<u8>& data)
|
||||
return;
|
||||
}
|
||||
|
||||
const u64 room_id = reinterpret_cast<le_t<u64>&>(data[0]);
|
||||
const u16 member_id = reinterpret_cast<le_t<u16>&>(data[8]);
|
||||
const u16 port_p2p = reinterpret_cast<be_t<u16>&>(data[10]);
|
||||
const u32 addr_p2p = reinterpret_cast<le_t<u32>&>(data[12]);
|
||||
const u64 room_id = reinterpret_cast<le_t<u64>&>(data[0]);
|
||||
const u16 member_id = reinterpret_cast<le_t<u16>&>(data[8]);
|
||||
const u16 port_p2p = reinterpret_cast<be_t<u16>&>(data[10]);
|
||||
const u32 addr_p2p = reinterpret_cast<le_t<u32>&>(data[12]);
|
||||
|
||||
rpcn_log.notice("Received notification to connect to member(%d) of room(%d): %s:%d", member_id, room_id, ip_to_string(addr_p2p), port_p2p);
|
||||
|
||||
@ -1193,7 +1321,7 @@ void np_handler::notif_room_message_received(std::vector<u8>& data)
|
||||
|
||||
u32 event_key = get_event_key();
|
||||
|
||||
auto message_info = flatbuffers::GetRoot<RoomMessageInfo>(message_info_raw.data());
|
||||
auto message_info = flatbuffers::GetRoot<RoomMessageInfo>(message_info_raw.data());
|
||||
SceNpMatching2RoomMessageInfo* notif_data = reinterpret_cast<SceNpMatching2RoomMessageInfo*>(allocate_req_result(event_key, sizeof(SceNpMatching2RoomMessageInfo)));
|
||||
RoomMessageInfo_to_SceNpMatching2RoomMessageInfo(message_info, notif_data);
|
||||
|
||||
@ -1202,10 +1330,10 @@ void np_handler::notif_room_message_received(std::vector<u8>& data)
|
||||
if (room_msg_cb)
|
||||
{
|
||||
sysutil_register_cb([room_msg_cb = this->room_msg_cb, room_msg_cb_ctx = this->room_msg_cb_ctx, room_id, member_id, event_key, room_msg_cb_arg = this->room_msg_cb_arg](ppu_thread& cb_ppu) -> s32
|
||||
{
|
||||
room_msg_cb(cb_ppu, room_msg_cb_ctx, room_id, member_id, SCE_NP_MATCHING2_ROOM_MSG_EVENT_Message, event_key, 0, sizeof(SceNpMatching2RoomUpdateInfo), room_msg_cb_arg);
|
||||
return 0;
|
||||
});
|
||||
{
|
||||
room_msg_cb(cb_ppu, room_msg_cb_ctx, room_id, member_id, SCE_NP_MATCHING2_ROOM_MSG_EVENT_Message, event_key, 0, sizeof(SceNpMatching2RoomUpdateInfo), room_msg_cb_arg);
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -1338,7 +1466,7 @@ s32 np_handler::analyze_dns_packet(s32 s, const u8* buf, u32 len)
|
||||
bool np_handler::error_and_disconnect(const std::string& error_msg)
|
||||
{
|
||||
rpcn_log.error("%s", error_msg);
|
||||
rpcn.disconnect();
|
||||
rpcn.reset();
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -1358,11 +1486,24 @@ u32 np_handler::generate_callback_info(SceNpMatching2ContextId ctx_id, vm::cptr<
|
||||
|
||||
nph_log.warning("Callback used is 0x%x", ret.cb);
|
||||
|
||||
pending_requests[req_id] = std::move(ret);
|
||||
{
|
||||
std::lock_guard lock(mutex_pending_requests);
|
||||
pending_requests[req_id] = std::move(ret);
|
||||
}
|
||||
|
||||
return req_id;
|
||||
}
|
||||
|
||||
np_handler::callback_info np_handler::take_pending_request(u32 req_id)
|
||||
{
|
||||
std::lock_guard lock(mutex_pending_requests);
|
||||
|
||||
const auto cb_info = std::move(pending_requests.at(req_id));
|
||||
pending_requests.erase(req_id);
|
||||
|
||||
return cb_info;
|
||||
}
|
||||
|
||||
u8* np_handler::allocate_req_result(u32 event_key, usz size)
|
||||
{
|
||||
std::lock_guard lock(mutex_req_results);
|
||||
@ -1385,3 +1526,13 @@ u32 np_handler::add_players_to_history(vm::cptr<SceNpId> /*npids*/, u32 /*count*
|
||||
|
||||
return req_id;
|
||||
}
|
||||
|
||||
u32 np_handler::get_num_friends()
|
||||
{
|
||||
return rpcn->get_num_friends();
|
||||
}
|
||||
|
||||
u32 np_handler::get_num_blocks()
|
||||
{
|
||||
return rpcn->get_num_blocks();
|
||||
}
|
||||
|
@ -35,9 +35,10 @@ public:
|
||||
static std::string ip_to_string(u32 addr);
|
||||
static std::string ether_to_string(std::array<u8, 6>& ether);
|
||||
// Helpers for setting various structures from string
|
||||
static void string_to_npid(const std::string&, SceNpId* npid);
|
||||
static void string_to_online_name(const std::string&, SceNpOnlineName* online_name);
|
||||
static void string_to_avatar_url(const std::string&, SceNpAvatarUrl* avatar_url);
|
||||
static void string_to_npid(const std::string& str, SceNpId* npid);
|
||||
static void string_to_online_name(const std::string& str, SceNpOnlineName* online_name);
|
||||
static void string_to_avatar_url(const std::string& str, SceNpAvatarUrl* avatar_url);
|
||||
static void string_to_communication_id(const std::string& str, SceNpCommunicationId* comm_id);
|
||||
|
||||
// DNS hooking functions
|
||||
void add_dns_spy(u32 sock);
|
||||
@ -47,16 +48,6 @@ public:
|
||||
std::vector<u8> get_dns_packet(u32 sock);
|
||||
s32 analyze_dns_packet(s32 s, const u8* buf, u32 len);
|
||||
|
||||
enum NotificationType : u16
|
||||
{
|
||||
UserJoinedRoom,
|
||||
UserLeftRoom,
|
||||
RoomDestroyed,
|
||||
SignalP2PConnect,
|
||||
_SignalP2PDisconnect,
|
||||
RoomMessageReceived,
|
||||
};
|
||||
|
||||
// handles async messages from server(only needed for RPCN)
|
||||
void operator()();
|
||||
|
||||
@ -73,12 +64,28 @@ public:
|
||||
|
||||
// NP Handlers/Callbacks
|
||||
// Seems to be global
|
||||
vm::ptr<SceNpManagerCallback> manager_cb{}; // Connection status and tickets
|
||||
vm::ptr<SceNpManagerCallback> manager_cb{}; // Connection status and tickets
|
||||
vm::ptr<void> manager_cb_arg{};
|
||||
|
||||
// Registered by SceNpCommunicationId
|
||||
vm::ptr<SceNpBasicEventHandler> basic_handler;
|
||||
vm::ptr<void> basic_handler_arg;
|
||||
// Basic event handler;
|
||||
struct
|
||||
{
|
||||
SceNpCommunicationId context{};
|
||||
vm::ptr<SceNpBasicEventHandler> handler_func;
|
||||
vm::ptr<void> handler_arg;
|
||||
bool registered = false;
|
||||
bool context_sensitive = false;
|
||||
} basic_handler;
|
||||
struct basic_event
|
||||
{
|
||||
s32 event = 0;
|
||||
SceNpUserInfo from{};
|
||||
std::vector<u8> data;
|
||||
};
|
||||
void queue_basic_event(basic_event to_queue);
|
||||
bool send_basic_event(s32 event, s32 retCode, u32 reqId);
|
||||
error_code get_basic_event(vm::ptr<s32> event, vm::ptr<SceNpUserInfo> from, vm::ptr<s32> data, vm::ptr<u32> size);
|
||||
std::optional<std::shared_ptr<std::pair<std::string, message_data>>> get_message(u64 id);
|
||||
|
||||
// Those should probably be under match2 ctx
|
||||
vm::ptr<SceNpMatching2RoomEventCallback> room_event_cb{}; // Room events
|
||||
@ -98,6 +105,7 @@ public:
|
||||
u32 join_room(SceNpMatching2ContextId ctx_id, vm::cptr<SceNpMatching2RequestOptParam> optParam, const SceNpMatching2JoinRoomRequest* req);
|
||||
u32 leave_room(SceNpMatching2ContextId ctx_id, vm::cptr<SceNpMatching2RequestOptParam> optParam, const SceNpMatching2LeaveRoomRequest* req);
|
||||
u32 search_room(SceNpMatching2ContextId ctx_id, vm::cptr<SceNpMatching2RequestOptParam> optParam, const SceNpMatching2SearchRoomRequest* req);
|
||||
u32 get_roomdata_external_list(SceNpMatching2ContextId ctx_id, vm::cptr<SceNpMatching2RequestOptParam> optParam, const SceNpMatching2GetRoomDataExternalListRequest* req);
|
||||
u32 set_roomdata_external(SceNpMatching2ContextId ctx_id, vm::cptr<SceNpMatching2RequestOptParam> optParam, const SceNpMatching2SetRoomDataExternalRequest* req);
|
||||
u32 get_roomdata_internal(SceNpMatching2ContextId ctx_id, vm::cptr<SceNpMatching2RequestOptParam> optParam, const SceNpMatching2GetRoomDataInternalRequest* req);
|
||||
u32 set_roomdata_internal(SceNpMatching2ContextId ctx_id, vm::cptr<SceNpMatching2RequestOptParam> optParam, const SceNpMatching2SetRoomDataInternalRequest* req);
|
||||
@ -106,9 +114,16 @@ public:
|
||||
|
||||
u32 get_match2_event(SceNpMatching2EventKey event_key, u8* dest, u32 size);
|
||||
|
||||
// Friend stuff
|
||||
u32 get_num_friends();
|
||||
u32 get_num_blocks();
|
||||
|
||||
// Misc stuff
|
||||
void req_ticket(u32 version, const SceNpId *npid, const char *service_id, const u8 *cookie, u32 cookie_size, const char *entitlement_id, u32 consumed_count);
|
||||
const std::vector<u8>& get_ticket() const { return current_ticket; }
|
||||
void req_ticket(u32 version, const SceNpId* npid, const char* service_id, const u8* cookie, u32 cookie_size, const char* entitlement_id, u32 consumed_count);
|
||||
const std::vector<u8>& get_ticket() const
|
||||
{
|
||||
return current_ticket;
|
||||
}
|
||||
u32 add_players_to_history(vm::cptr<SceNpId> npids, u32 count);
|
||||
|
||||
// For signaling
|
||||
@ -119,7 +134,7 @@ public:
|
||||
|
||||
static constexpr std::string_view thread_name = "NP Handler Thread";
|
||||
|
||||
protected:
|
||||
private:
|
||||
// Various generic helpers
|
||||
bool discover_ip_address();
|
||||
bool discover_ether_address();
|
||||
@ -138,6 +153,7 @@ protected:
|
||||
bool reply_join_room(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_leave_room(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_search_room(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_get_roomdata_external_list(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_set_roomdata_external(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_get_roomdata_internal(u32 req_id, std::vector<u8>& reply_data);
|
||||
bool reply_set_roomdata_internal(u32 req_id, std::vector<u8>& reply_data);
|
||||
@ -150,7 +166,9 @@ protected:
|
||||
void BinAttr_to_SceNpMatching2BinAttr(const flatbuffers::Vector<flatbuffers::Offset<BinAttr>>* fb_attr, vm::ptr<SceNpMatching2BinAttr> binattr_info);
|
||||
void RoomGroup_to_SceNpMatching2RoomGroup(const flatbuffers::Vector<flatbuffers::Offset<RoomGroup>>* fb_group, vm::ptr<SceNpMatching2RoomGroup> group_info);
|
||||
void UserInfo2_to_SceNpUserInfo2(const UserInfo2* user, SceNpUserInfo2* user_info);
|
||||
void SearchRoomReponse_to_SceNpMatching2SearchRoomResponse(const SearchRoomResponse* resp, SceNpMatching2SearchRoomResponse* search_resp);
|
||||
void RoomDataExternal_to_SceNpMatching2RoomDataExternal(const RoomDataExternal* room, SceNpMatching2RoomDataExternal* room_info);
|
||||
void SearchRoomResponse_to_SceNpMatching2SearchRoomResponse(const SearchRoomResponse* resp, SceNpMatching2SearchRoomResponse* search_resp);
|
||||
void GetRoomDataExternalListResponse_to_SceNpMatching2GetRoomDataExternalListResponse(const GetRoomDataExternalListResponse* resp, SceNpMatching2GetRoomDataExternalListResponse* get_resp);
|
||||
u16 RoomDataInternal_to_SceNpMatching2RoomDataInternal(const RoomDataInternal* resp, SceNpMatching2RoomDataInternal* room_resp, const SceNpId& npid);
|
||||
void RoomMemberUpdateInfo_to_SceNpMatching2RoomMemberUpdateInfo(const RoomMemberUpdateInfo* resp, SceNpMatching2RoomMemberUpdateInfo* room_info);
|
||||
void RoomUpdateInfo_to_SceNpMatching2RoomUpdateInfo(const RoomUpdateInfo* update_info, SceNpMatching2RoomUpdateInfo* sce_update_info);
|
||||
@ -164,11 +182,17 @@ protected:
|
||||
vm::ptr<void> cb_arg;
|
||||
};
|
||||
u32 generate_callback_info(SceNpMatching2ContextId ctx_id, vm::cptr<SceNpMatching2RequestOptParam> optParam);
|
||||
callback_info take_pending_request(u32 req_id);
|
||||
|
||||
shared_mutex mutex_pending_requests;
|
||||
std::unordered_map<u32, callback_info> pending_requests;
|
||||
shared_mutex mutex_pending_sign_infos_requests;
|
||||
std::unordered_map<u32, u32> pending_sign_infos_requests;
|
||||
|
||||
protected:
|
||||
shared_mutex mutex_queue_basic_events;
|
||||
std::queue<basic_event> queue_basic_events;
|
||||
|
||||
private:
|
||||
bool is_connected = false;
|
||||
bool is_psn_active = false;
|
||||
|
||||
@ -213,5 +237,6 @@ protected:
|
||||
u8* allocate_req_result(u32 event_key, usz size);
|
||||
|
||||
// RPCN
|
||||
rpcn_client rpcn;
|
||||
shared_mutex mutex_rpcn;
|
||||
std::shared_ptr<rpcn::rpcn_client> rpcn;
|
||||
};
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -2,6 +2,8 @@
|
||||
|
||||
#include <unordered_map>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include <semaphore>
|
||||
#include "Utilities/mutex.h"
|
||||
|
||||
#include "util/asm.hpp"
|
||||
@ -26,8 +28,7 @@ class vec_stream
|
||||
public:
|
||||
vec_stream() = delete;
|
||||
vec_stream(std::vector<u8>& _vec, usz initial_index = 0)
|
||||
: vec(_vec)
|
||||
, i(initial_index){}
|
||||
: vec(_vec), i(initial_index) {}
|
||||
bool is_error() const
|
||||
{
|
||||
return error;
|
||||
@ -97,33 +98,70 @@ public:
|
||||
|
||||
protected:
|
||||
std::vector<u8>& vec;
|
||||
usz i = 0;
|
||||
usz i = 0;
|
||||
bool error = false;
|
||||
};
|
||||
|
||||
enum CommandType : u16
|
||||
namespace rpcn
|
||||
{
|
||||
Login,
|
||||
Terminate,
|
||||
Create,
|
||||
SendToken,
|
||||
GetServerList,
|
||||
GetWorldList,
|
||||
CreateRoom,
|
||||
JoinRoom,
|
||||
LeaveRoom,
|
||||
SearchRoom,
|
||||
SetRoomDataExternal,
|
||||
GetRoomDataInternal,
|
||||
SetRoomDataInternal,
|
||||
PingRoomOwner,
|
||||
SendRoomMessage,
|
||||
RequestSignalingInfos,
|
||||
RequestTicket,
|
||||
};
|
||||
enum CommandType : u16
|
||||
{
|
||||
Login,
|
||||
Terminate,
|
||||
Create,
|
||||
SendToken,
|
||||
AddFriend,
|
||||
RemoveFriend,
|
||||
AddBlock,
|
||||
RemoveBlock,
|
||||
GetServerList,
|
||||
GetWorldList,
|
||||
CreateRoom,
|
||||
JoinRoom,
|
||||
LeaveRoom,
|
||||
SearchRoom,
|
||||
GetRoomDataExternalList,
|
||||
SetRoomDataExternal,
|
||||
GetRoomDataInternal,
|
||||
SetRoomDataInternal,
|
||||
PingRoomOwner,
|
||||
SendRoomMessage,
|
||||
RequestSignalingInfos,
|
||||
RequestTicket,
|
||||
SendMessage,
|
||||
};
|
||||
|
||||
enum NotificationType : u16
|
||||
{
|
||||
UserJoinedRoom,
|
||||
UserLeftRoom,
|
||||
RoomDestroyed,
|
||||
SignalP2PConnect,
|
||||
_SignalP2PDisconnect,
|
||||
FriendQuery, // Other user sent a friend request
|
||||
FriendNew, // Add a friend to the friendlist(either accepted a friend request or friend accepted it)
|
||||
FriendLost, // Remove friend from the friendlist(user removed friend or friend removed friend)
|
||||
FriendStatus, // Set status of friend to Offline or Online
|
||||
RoomMessageReceived,
|
||||
MessageReceived,
|
||||
};
|
||||
|
||||
enum class rpcn_state
|
||||
{
|
||||
failure_no_failure,
|
||||
failure_input,
|
||||
failure_wolfssl,
|
||||
failure_resolve,
|
||||
failure_connect,
|
||||
failure_id,
|
||||
failure_id_already_logged_in,
|
||||
failure_id_username,
|
||||
failure_id_password,
|
||||
failure_id_token,
|
||||
failure_protocol,
|
||||
failure_other,
|
||||
};
|
||||
|
||||
class rpcn_client
|
||||
{
|
||||
enum PacketType : u8
|
||||
{
|
||||
Request,
|
||||
@ -134,123 +172,245 @@ class rpcn_client
|
||||
|
||||
enum ErrorType : u8
|
||||
{
|
||||
NoError,
|
||||
Malformed,
|
||||
Invalid,
|
||||
InvalidInput,
|
||||
ErrorLogin,
|
||||
ErrorCreate,
|
||||
AlreadyLoggedIn,
|
||||
AlreadyJoined,
|
||||
DbFail,
|
||||
NotFound,
|
||||
NoError, // No error
|
||||
Malformed, // Query was malformed, critical error that should close the connection
|
||||
Invalid, // The request type is invalid(wrong stage?)
|
||||
InvalidInput, // The Input doesn't fit the constraints of the request
|
||||
TooSoon, // Time limited operation attempted too soon
|
||||
LoginError, // An error happened related to login
|
||||
LoginAlreadyLoggedIn, // Can't log in because you're already logged in
|
||||
LoginInvalidUsername, // Invalid username
|
||||
LoginInvalidPassword, // Invalid password
|
||||
LoginInvalidToken, // Invalid token
|
||||
CreationError, // An error happened related to account creation
|
||||
CreationExistingUsername, // Specific
|
||||
CreationBannedEmailProvider, // Specific to Account Creation: the email provider is banned
|
||||
CreationExistingEmail, // Specific to Account Creation: that email is already registered to an account
|
||||
AlreadyJoined, // User tried to join a room he's already part of
|
||||
DbFail, // Generic failure on db side
|
||||
EmailFail, // Generic failure related to email
|
||||
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
|
||||
Unsupported,
|
||||
__error_last
|
||||
};
|
||||
|
||||
public:
|
||||
rpcn_client(bool in_config = false);
|
||||
~rpcn_client();
|
||||
using friend_cb_func = void (*)(void* param, NotificationType ntype, const std::string& username, bool status);
|
||||
using message_cb_func = void (*)(void* param, const std::shared_ptr<std::pair<std::string, message_data>> new_msg, u64 msg_id);
|
||||
|
||||
bool connect(const std::string& host);
|
||||
bool login(const std::string& npid, const std::string& password, const std::string& token);
|
||||
bool create_user(const std::string& npid, const std::string& password, const std::string& online_name, const std::string& avatar_url, const std::string& email);
|
||||
void disconnect();
|
||||
bool manage_connection();
|
||||
std::vector<std::pair<u16, std::vector<u8>>> get_notifications();
|
||||
std::unordered_map<u32, std::pair<u16, std::vector<u8>>> get_replies();
|
||||
void abort();
|
||||
|
||||
// Synchronous requests
|
||||
bool get_server_list(u32 req_id, const SceNpCommunicationId& communication_id, std::vector<u16>& server_list);
|
||||
// Asynchronous requests
|
||||
bool get_world_list(u32 req_id, const SceNpCommunicationId& communication_id, u16 server_id);
|
||||
bool createjoin_room(u32 req_id,const SceNpCommunicationId& communication_id, const SceNpMatching2CreateJoinRoomRequest* req);
|
||||
bool join_room(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2JoinRoomRequest* req);
|
||||
bool leave_room(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2LeaveRoomRequest* req);
|
||||
bool search_room(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2SearchRoomRequest* req);
|
||||
bool set_roomdata_external(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2SetRoomDataExternalRequest* req);
|
||||
bool get_roomdata_internal(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2GetRoomDataInternalRequest* req);
|
||||
bool set_roomdata_internal(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2SetRoomDataInternalRequest* req);
|
||||
bool ping_room_owner(u32 req_id, const SceNpCommunicationId& communication_id, u64 room_id);
|
||||
bool send_room_message(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2SendRoomMessageRequest* req);
|
||||
bool req_sign_infos(u32 req_id, const std::string& npid);
|
||||
bool req_ticket(u32 req_id, const std::string& service_id);
|
||||
|
||||
const std::string& get_online_name() const
|
||||
struct friend_data
|
||||
{
|
||||
return online_name;
|
||||
}
|
||||
const std::string& get_avatar_url() const
|
||||
{
|
||||
return avatar_url;
|
||||
}
|
||||
|
||||
u32 get_addr_sig() const
|
||||
{
|
||||
return addr_sig.load();
|
||||
}
|
||||
u16 get_port_sig() const
|
||||
{
|
||||
return port_sig.load();
|
||||
}
|
||||
|
||||
protected:
|
||||
enum class recvn_result
|
||||
{
|
||||
recvn_success,
|
||||
recvn_nodata,
|
||||
recvn_timeout,
|
||||
recvn_noconn,
|
||||
recvn_fatal,
|
||||
std::map<std::string, std::pair<bool, u64>> friends;
|
||||
std::set<std::string> requests_sent;
|
||||
std::set<std::string> requests_received;
|
||||
std::set<std::string> blocked;
|
||||
};
|
||||
|
||||
recvn_result recvn(u8* buf, usz n);
|
||||
class rpcn_client
|
||||
{
|
||||
private:
|
||||
static inline std::weak_ptr<rpcn_client> instance;
|
||||
static inline shared_mutex inst_mutex;
|
||||
|
||||
bool get_reply(u32 expected_id, std::vector<u8>& data);
|
||||
atomic_t<bool> connected = false;
|
||||
atomic_t<bool> authentified = false;
|
||||
atomic_t<bool> want_auth = false;
|
||||
std::binary_semaphore sem_connected, sem_authentified;
|
||||
std::mutex mutex_connected, mutex_authentified;
|
||||
|
||||
std::vector<u8> forge_request(u16 command, u32 packet_id, const std::vector<u8>& data) const;
|
||||
bool send_packet(const std::vector<u8>& packet);
|
||||
bool forge_send(u16 command, u32 packet_id, const std::vector<u8>& data);
|
||||
bool forge_send_reply(u16 command, u32 packet_id, const std::vector<u8>& data, std::vector<u8>& reply_data);
|
||||
std::binary_semaphore sem_reader, sem_writer, sem_rpcn;
|
||||
std::mutex mutex_read, mutex_write;
|
||||
|
||||
bool is_error(ErrorType err) const;
|
||||
bool error_and_disconnect(const std::string& error_mgs);
|
||||
bool is_abort() const;
|
||||
std::thread thread_rpcn, thread_rpcn_reader, thread_rpcn_writer;
|
||||
|
||||
std::string get_wolfssl_error(int error) const;
|
||||
atomic_t<bool> terminate = false;
|
||||
|
||||
protected:
|
||||
atomic_t<bool> connected = false;
|
||||
atomic_t<bool> authentified = false;
|
||||
atomic_t<u32> num_failures = 0;
|
||||
atomic_t<rpcn_state> state = rpcn_state::failure_no_failure;
|
||||
|
||||
WOLFSSL_CTX* wssl_ctx = nullptr;
|
||||
WOLFSSL* wssl = nullptr;
|
||||
std::vector<std::vector<u8>> packets_to_send;
|
||||
std::mutex mutex_packets_to_send;
|
||||
|
||||
bool in_config = false;
|
||||
bool abort_config = false;
|
||||
// Friends related
|
||||
shared_mutex mutex_friends;
|
||||
std::set<std::pair<friend_cb_func, void*>> friend_cbs;
|
||||
friend_data friend_infos;
|
||||
|
||||
atomic_t<bool> server_info_received = false;
|
||||
u32 received_version = 0;
|
||||
void handle_friend_notification(u16 command, std::vector<u8> data);
|
||||
|
||||
// UDP Signaling related
|
||||
steady_clock::time_point last_ping_time{}, last_pong_time{};
|
||||
void handle_message(std::vector<u8> data);
|
||||
|
||||
sockaddr_in addr_rpcn{};
|
||||
sockaddr_in addr_rpcn_udp{};
|
||||
int sockfd = 0;
|
||||
shared_mutex mutex_socket;
|
||||
private:
|
||||
rpcn_client();
|
||||
|
||||
shared_mutex mutex_notifs, mutex_replies, mutex_replies_sync;
|
||||
std::vector<std::pair<u16, std::vector<u8>>> notifications; // notif type / data
|
||||
std::unordered_map<u32, std::pair<u16, std::vector<u8>>> replies; // req id / (command / data)
|
||||
std::unordered_map<u32, std::pair<u16, std::vector<u8>>> replies_sync; // same but for sync replies(Login, Create, GetServerList)
|
||||
void rpcn_reader_thread();
|
||||
void rpcn_writer_thread();
|
||||
void rpcn_thread();
|
||||
|
||||
std::string online_name{};
|
||||
std::string avatar_url{};
|
||||
bool handle_input();
|
||||
bool handle_output();
|
||||
|
||||
s64 user_id = 0;
|
||||
void add_packet(const std::vector<u8> packet);
|
||||
|
||||
atomic_t<u32> addr_sig{};
|
||||
atomic_t<u16> port_sig{};
|
||||
};
|
||||
private:
|
||||
enum class recvn_result
|
||||
{
|
||||
recvn_success,
|
||||
recvn_nodata,
|
||||
recvn_timeout,
|
||||
recvn_noconn,
|
||||
recvn_terminate,
|
||||
recvn_fatal,
|
||||
};
|
||||
|
||||
recvn_result recvn(u8* buf, usz n);
|
||||
bool send_packet(const std::vector<u8>& packet);
|
||||
|
||||
private:
|
||||
bool connect(const std::string& host);
|
||||
bool login(const std::string& npid, const std::string& password, const std::string& token);
|
||||
void disconnect();
|
||||
|
||||
public:
|
||||
~rpcn_client();
|
||||
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();
|
||||
rpcn_state wait_for_authentified();
|
||||
|
||||
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);
|
||||
bool add_friend(const std::string& friend_username);
|
||||
bool remove_friend(const std::string& friend_username);
|
||||
|
||||
u32 get_num_friends() const;
|
||||
u32 get_num_blocks() const;
|
||||
|
||||
std::vector<std::pair<u16, std::vector<u8>>> get_notifications();
|
||||
std::unordered_map<u32, std::pair<u16, std::vector<u8>>> get_replies();
|
||||
|
||||
std::vector<u64> get_new_messages();
|
||||
std::optional<std::shared_ptr<std::pair<std::string, message_data>>> get_message(u64 id);
|
||||
std::vector<std::pair<u64, std::shared_ptr<std::pair<std::string, message_data>>>> get_messages_and_register_cb(SceNpBasicMessageMainType type, bool include_bootable, message_cb_func cb_func, void* cb_param);
|
||||
void remove_message_cb(message_cb_func cb_func, void* cb_param);
|
||||
void discard_active_message(u64 id);
|
||||
|
||||
bool is_connected() const
|
||||
{
|
||||
return connected;
|
||||
}
|
||||
bool is_authentified() const
|
||||
{
|
||||
return authentified;
|
||||
}
|
||||
rpcn_state get_rpcn_state() const
|
||||
{
|
||||
return state;
|
||||
}
|
||||
|
||||
void server_infos_updated();
|
||||
|
||||
// Synchronous requests
|
||||
bool get_server_list(u32 req_id, const SceNpCommunicationId& communication_id, std::vector<u16>& server_list);
|
||||
// Asynchronous requests
|
||||
bool get_world_list(u32 req_id, const SceNpCommunicationId& communication_id, u16 server_id);
|
||||
bool createjoin_room(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2CreateJoinRoomRequest* req);
|
||||
bool join_room(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2JoinRoomRequest* req);
|
||||
bool leave_room(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2LeaveRoomRequest* req);
|
||||
bool search_room(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2SearchRoomRequest* req);
|
||||
bool get_roomdata_external_list(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2GetRoomDataExternalListRequest* req);
|
||||
bool set_roomdata_external(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2SetRoomDataExternalRequest* req);
|
||||
bool get_roomdata_internal(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2GetRoomDataInternalRequest* req);
|
||||
bool set_roomdata_internal(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2SetRoomDataInternalRequest* req);
|
||||
bool ping_room_owner(u32 req_id, const SceNpCommunicationId& communication_id, u64 room_id);
|
||||
bool send_room_message(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2SendRoomMessageRequest* req);
|
||||
bool req_sign_infos(u32 req_id, const std::string& npid);
|
||||
bool req_ticket(u32 req_id, const std::string& service_id);
|
||||
bool sendmessage(const message_data& msg_data, const std::set<std::string>& npids);
|
||||
|
||||
const std::string& get_online_name() const
|
||||
{
|
||||
return online_name;
|
||||
}
|
||||
const std::string& get_avatar_url() const
|
||||
{
|
||||
return avatar_url;
|
||||
}
|
||||
|
||||
u32 get_addr_sig() const
|
||||
{
|
||||
return addr_sig.load();
|
||||
}
|
||||
u16 get_port_sig() const
|
||||
{
|
||||
return port_sig.load();
|
||||
}
|
||||
|
||||
private:
|
||||
bool get_reply(u64 expected_id, std::vector<u8>& data);
|
||||
|
||||
std::vector<u8> forge_request(u16 command, u64 packet_id, const std::vector<u8>& data) const;
|
||||
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;
|
||||
|
||||
private:
|
||||
WOLFSSL_CTX* wssl_ctx = nullptr;
|
||||
WOLFSSL* read_wssl = nullptr;
|
||||
WOLFSSL* write_wssl = nullptr;
|
||||
|
||||
atomic_t<bool> server_info_received = false;
|
||||
u32 received_version = 0;
|
||||
|
||||
// UDP Signaling related
|
||||
steady_clock::time_point last_ping_time{}, last_pong_time{};
|
||||
|
||||
sockaddr_in addr_rpcn{};
|
||||
sockaddr_in addr_rpcn_udp{};
|
||||
int sockfd = 0;
|
||||
|
||||
atomic_t<u64> rpcn_request_counter = 0x100000001; // Counter used for commands whose result is not forwarded to NP handler(login, create, sendmessage, etc)
|
||||
|
||||
shared_mutex mutex_notifs, mutex_replies, mutex_replies_sync;
|
||||
std::vector<std::pair<u16, std::vector<u8>>> notifications; // notif type / data
|
||||
std::unordered_map<u32, std::pair<u16, std::vector<u8>>> replies; // req id / (command / data)
|
||||
std::unordered_map<u64, std::pair<u16, std::vector<u8>>> replies_sync; // same but for sync replies(Login, Create, GetServerList)
|
||||
|
||||
// Messages
|
||||
struct message_cb_t
|
||||
{
|
||||
message_cb_func cb_func;
|
||||
void* cb_param;
|
||||
SceNpBasicMessageMainType type_filter;
|
||||
bool inc_bootable;
|
||||
|
||||
bool operator<(const message_cb_t& other) const
|
||||
{
|
||||
return (cb_func < other.cb_func) || ((!(other.cb_func < cb_func)) && (cb_param < other.cb_param));
|
||||
}
|
||||
};
|
||||
shared_mutex mutex_messages;
|
||||
std::set<message_cb_t> message_cbs;
|
||||
std::unordered_map<u64, std::shared_ptr<std::pair<std::string, message_data>>> messages; // msg id / (sender / message)
|
||||
std::set<u64> active_messages; // msg id of messages that have not been discarded
|
||||
std::vector<u64> new_messages; // list of msg_id used to inform np_handler of new messages
|
||||
u64 message_counter = 3; // id counter
|
||||
|
||||
std::string online_name{};
|
||||
std::string avatar_url{};
|
||||
|
||||
s64 user_id = 0;
|
||||
|
||||
atomic_t<u32> addr_sig{};
|
||||
atomic_t<u16> port_sig{};
|
||||
};
|
||||
|
||||
} // namespace rpcn
|
||||
|
@ -290,6 +290,7 @@ void signaling_handler::process_incoming_messages()
|
||||
retire_packet(si, signal_connect);
|
||||
// connection is active
|
||||
update_si_addr(si, op_addr, op_port);
|
||||
update_si_mapped_addr(si, sp->sent_addr, sp->sent_port);
|
||||
update_si_status(si, SCE_NP_SIGNALING_CONN_STATUS_ACTIVE);
|
||||
break;
|
||||
case signal_confirm:
|
||||
@ -299,6 +300,7 @@ void signaling_handler::process_incoming_messages()
|
||||
retire_packet(si, signal_connect_ack);
|
||||
// connection is active
|
||||
update_si_addr(si, op_addr, op_port);
|
||||
update_si_mapped_addr(si, sp->sent_addr, sp->sent_port);
|
||||
update_si_status(si, SCE_NP_SIGNALING_CONN_STATUS_ACTIVE, true);
|
||||
break;
|
||||
case signal_finished:
|
||||
@ -418,6 +420,27 @@ void signaling_handler::update_si_addr(std::shared_ptr<signaling_info>& si, u32
|
||||
}
|
||||
}
|
||||
|
||||
void signaling_handler::update_si_mapped_addr(std::shared_ptr<signaling_info>& si, u32 new_addr, u16 new_port)
|
||||
{
|
||||
ensure(si);
|
||||
|
||||
if (si->addr != new_addr || si->port != new_port)
|
||||
{
|
||||
in_addr addr_old, addr_new;
|
||||
addr_old.s_addr = si->addr;
|
||||
addr_new.s_addr = new_addr;
|
||||
|
||||
char ip_str_old[16];
|
||||
char ip_str_new[16];
|
||||
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);
|
||||
si->mapped_addr = new_addr;
|
||||
si->mapped_port = new_port;
|
||||
}
|
||||
}
|
||||
|
||||
void signaling_handler::update_si_status(std::shared_ptr<signaling_info>& si, s32 new_status, bool confirm_packet)
|
||||
{
|
||||
if (!si)
|
||||
@ -485,6 +508,9 @@ 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);
|
||||
|
@ -21,6 +21,10 @@ struct signaling_info
|
||||
u32 addr = 0;
|
||||
u16 port = 0;
|
||||
|
||||
// User seen from that peer
|
||||
u32 mapped_addr = 0;
|
||||
u16 mapped_port = 0;
|
||||
|
||||
// For handler
|
||||
steady_clock::time_point time_last_msg_recvd = steady_clock::now();
|
||||
|
||||
@ -84,6 +88,8 @@ private:
|
||||
be_t<u32> signature = SIGNALING_SIGNATURE;
|
||||
le_t<u32> version;
|
||||
le_t<SignalingCommand> command;
|
||||
le_t<u32> sent_addr;
|
||||
le_t<u16> sent_port;
|
||||
union {
|
||||
struct
|
||||
{
|
||||
@ -117,6 +123,7 @@ private:
|
||||
|
||||
u32 create_sig_infos(const SceNpId* npid);
|
||||
static void update_si_addr(std::shared_ptr<signaling_info>& si, u32 new_addr, u16 new_port);
|
||||
static void update_si_mapped_addr(std::shared_ptr<signaling_info>& si, u32 new_addr, u16 new_port);
|
||||
void update_si_status(std::shared_ptr<signaling_info>& si, s32 new_status, bool confirm_packet = false);
|
||||
void signal_sig_callback(u32 conn_id, int event);
|
||||
void signal_ext_sig_callback(u32 conn_id, int event) const;
|
||||
|
@ -74,6 +74,8 @@ struct EmuCallbacks
|
||||
std::function<std::shared_ptr<class MsgDialogBase>()> get_msg_dialog;
|
||||
std::function<std::shared_ptr<class OskDialogBase>()> get_osk_dialog;
|
||||
std::function<std::unique_ptr<class SaveDialogBase>()> get_save_dialog;
|
||||
std::function<std::shared_ptr<class SendMessageDialogBase>()> get_sendmessage_dialog;
|
||||
std::function<std::shared_ptr<class RecvMessageDialogBase>()> get_recvmessage_dialog;
|
||||
std::function<std::unique_ptr<class TrophyNotificationBase>()> get_trophy_notification_dialog;
|
||||
std::function<std::string(localized_string_id, const char*)> get_localized_string;
|
||||
std::function<std::u32string(localized_string_id, const char*)> get_localized_u32string;
|
||||
|
@ -247,8 +247,8 @@ void fmt_class_string<np_psn_status>::format(std::string& out, u64 arg)
|
||||
switch (value)
|
||||
{
|
||||
case np_psn_status::disabled: return "Disconnected";
|
||||
case np_psn_status::fake: return "Simulated";
|
||||
case np_psn_status::rpcn: return "RPCN";
|
||||
case np_psn_status::psn_fake: return "Simulated";
|
||||
case np_psn_status::psn_rpcn: return "RPCN";
|
||||
}
|
||||
|
||||
return unknown;
|
||||
|
@ -184,8 +184,8 @@ enum class np_internet_status
|
||||
enum np_psn_status
|
||||
{
|
||||
disabled,
|
||||
fake,
|
||||
rpcn,
|
||||
psn_fake,
|
||||
psn_rpcn,
|
||||
};
|
||||
|
||||
enum class shader_mode
|
||||
|
@ -303,6 +303,9 @@
|
||||
<ClCompile Include="QTGeneratedFiles\Debug\moc_pkg_install_dialog.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Debug\moc_recvmessage_dialog_frame.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Debug\moc_register_editor_dialog.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
@ -330,6 +333,9 @@
|
||||
<ClCompile Include="QTGeneratedFiles\Debug\moc_screenshot_preview.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Debug\moc_sendmessage_dialog_frame.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Debug\moc_settings.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
@ -495,6 +501,9 @@
|
||||
<ClCompile Include="QTGeneratedFiles\Release\moc_pkg_install_dialog.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Release\moc_recvmessage_dialog_frame.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Release\moc_register_editor_dialog.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
@ -522,6 +531,9 @@
|
||||
<ClCompile Include="QTGeneratedFiles\Release\moc_screenshot_preview.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Release\moc_sendmessage_dialog_frame.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Release\moc_settings.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
@ -582,10 +594,12 @@
|
||||
<ClCompile Include="rpcs3qt\patch_manager_dialog.cpp" />
|
||||
<ClCompile Include="rpcs3qt\pkg_install_dialog.cpp" />
|
||||
<ClCompile Include="rpcs3qt\persistent_settings.cpp" />
|
||||
<ClCompile Include="rpcs3qt\recvmessage_dialog_frame.cpp" />
|
||||
<ClCompile Include="rpcs3qt\render_creator.cpp" />
|
||||
<ClCompile Include="rpcs3qt\rpcn_settings_dialog.cpp" />
|
||||
<ClCompile Include="rpcs3qt\screenshot_manager_dialog.cpp" />
|
||||
<ClCompile Include="rpcs3qt\screenshot_preview.cpp" />
|
||||
<ClCompile Include="rpcs3qt\sendmessage_dialog_frame.cpp" />
|
||||
<ClCompile Include="rpcs3qt\settings.cpp" />
|
||||
<ClCompile Include="rpcs3qt\skylander_dialog.cpp" />
|
||||
<ClCompile Include="rpcs3qt\tooltips.cpp" />
|
||||
@ -1064,7 +1078,27 @@
|
||||
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
||||
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\recvmessage_dialog_frame.h">
|
||||
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Moc%27ing %(Identity)...</Message>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\flatbuffers\include" "-I.\..\3rdparty\wolfssl\wolfssl" "-I.\..\3rdparty\curl\curl\include" "-I.\..\3rdparty\libusb\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\XAudio2Redist\include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtCore" "-I.\debug" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(QTDIR)\include\QtConcurrent"</Command>
|
||||
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Moc%27ing %(Identity)...</Message>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DWITH_DISCORD_RPC -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DNDEBUG -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\flatbuffers\include" "-I.\..\3rdparty\wolfssl\wolfssl" "-I.\..\3rdparty\curl\curl\include" "-I.\..\3rdparty\libusb\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\XAudio2Redist\include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtCore" "-I.\release" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(QTDIR)\include\QtConcurrent"</Command>
|
||||
</CustomBuild>
|
||||
<ClInclude Include="rpcs3qt\richtext_item_delegate.h" />
|
||||
<CustomBuild Include="rpcs3qt\sendmessage_dialog_frame.h">
|
||||
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Moc%27ing %(Identity)...</Message>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\flatbuffers\include" "-I.\..\3rdparty\wolfssl\wolfssl" "-I.\..\3rdparty\curl\curl\include" "-I.\..\3rdparty\libusb\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\XAudio2Redist\include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtCore" "-I.\debug" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(QTDIR)\include\QtConcurrent"</Command>
|
||||
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Moc%27ing %(Identity)...</Message>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DWITH_DISCORD_RPC -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DNDEBUG -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\flatbuffers\include" "-I.\..\3rdparty\wolfssl\wolfssl" "-I.\..\3rdparty\curl\curl\include" "-I.\..\3rdparty\libusb\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\XAudio2Redist\include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtCore" "-I.\release" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(QTDIR)\include\QtConcurrent"</Command>
|
||||
</CustomBuild>
|
||||
<ClInclude Include="rpcs3qt\stylesheets.h" />
|
||||
<CustomBuild Include="rpcs3qt\skylander_dialog.h">
|
||||
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
||||
|
@ -130,6 +130,9 @@
|
||||
<Filter Include="Gui\custom items">
|
||||
<UniqueIdentifier>{949cff6d-9cc5-4a8a-a453-a5144da8ecf4}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Gui\rpcn">
|
||||
<UniqueIdentifier>{dfd401ec-dd22-4f8a-9dea-565a03efab6a}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp">
|
||||
@ -711,9 +714,6 @@
|
||||
<ClCompile Include="QTGeneratedFiles\Release\moc_downloader.cpp">
|
||||
<Filter>Generated Files\Release</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\rpcn_settings_dialog.cpp">
|
||||
<Filter>Gui\settings</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Debug\moc_rpcn_settings_dialog.cpp">
|
||||
<Filter>Generated Files\Debug</Filter>
|
||||
</ClCompile>
|
||||
@ -756,6 +756,27 @@
|
||||
<ClCompile Include="QTGeneratedFiles\Release\moc_patch_creator_dialog.cpp">
|
||||
<Filter>Generated Files\Release</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\rpcn_settings_dialog.cpp">
|
||||
<Filter>Gui\rpcn</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\sendmessage_dialog_frame.cpp">
|
||||
<Filter>Gui\message dialog</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Debug\moc_sendmessage_dialog_frame.cpp">
|
||||
<Filter>Generated Files\Debug</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Release\moc_sendmessage_dialog_frame.cpp">
|
||||
<Filter>Generated Files\Release</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\recvmessage_dialog_frame.cpp">
|
||||
<Filter>Gui\message dialog</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Debug\moc_recvmessage_dialog_frame.cpp">
|
||||
<Filter>Generated Files\Debug</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Release\moc_recvmessage_dialog_frame.cpp">
|
||||
<Filter>Generated Files\Release</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Input\ds4_pad_handler.h">
|
||||
@ -1096,9 +1117,6 @@
|
||||
<CustomBuild Include="rpcs3qt\downloader.h">
|
||||
<Filter>Gui\network</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\rpcn_settings_dialog.h">
|
||||
<Filter>Gui\settings</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\localized_emu.h">
|
||||
<Filter>Gui\settings</Filter>
|
||||
</CustomBuild>
|
||||
@ -1111,6 +1129,15 @@
|
||||
<CustomBuild Include="rpcs3qt\patch_creator_dialog.h">
|
||||
<Filter>Gui\patch manager</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\rpcn_settings_dialog.h">
|
||||
<Filter>Gui\rpcn</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\sendmessage_dialog_frame.h">
|
||||
<Filter>Gui\message dialog</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\recvmessage_dialog_frame.h">
|
||||
<Filter>Gui\message dialog</Filter>
|
||||
</CustomBuild>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="rpcs3.ico" />
|
||||
|
@ -51,6 +51,7 @@ set(SRC_FILES
|
||||
progress_dialog.cpp
|
||||
qt_utils.cpp
|
||||
register_editor_dialog.cpp
|
||||
recvmessage_dialog_frame.cpp
|
||||
render_creator.cpp
|
||||
rpcn_settings_dialog.cpp
|
||||
rsx_debugger.cpp
|
||||
@ -60,6 +61,7 @@ set(SRC_FILES
|
||||
save_manager_dialog.cpp
|
||||
screenshot_manager_dialog.cpp
|
||||
screenshot_preview.cpp
|
||||
sendmessage_dialog_frame.cpp
|
||||
settings.cpp
|
||||
settings_dialog.cpp
|
||||
skylander_dialog.cpp
|
||||
|
@ -1041,8 +1041,8 @@ QString emu_settings::GetLocalizedSetting(const QString& original, emu_settings_
|
||||
switch (static_cast<np_psn_status>(index))
|
||||
{
|
||||
case np_psn_status::disabled: return tr("Disconnected", "PSN Status");
|
||||
case np_psn_status::fake: return tr("Simulated", "PSN Status");
|
||||
case np_psn_status::rpcn: return tr("RPCN", "PSN Status");
|
||||
case np_psn_status::psn_fake: return tr("Simulated", "PSN Status");
|
||||
case np_psn_status::psn_rpcn: return tr("RPCN", "PSN Status");
|
||||
}
|
||||
break;
|
||||
case emu_settings_type::SleepTimersAccuracy:
|
||||
|
@ -163,19 +163,3 @@ private Q_SLOTS:
|
||||
void handle_download_error(const QString& error);
|
||||
void handle_download_finished(const QByteArray& content);
|
||||
};
|
||||
|
||||
class compat_pixmap : public QPixmap
|
||||
{
|
||||
public:
|
||||
compat_pixmap(const QColor& color, qreal pixel_ratio) : QPixmap(pixel_ratio * 16, pixel_ratio * 16)
|
||||
{
|
||||
fill(Qt::transparent);
|
||||
|
||||
QPainter painter(this);
|
||||
setDevicePixelRatio(pixel_ratio);
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
painter.setPen(Qt::NoPen);
|
||||
painter.setBrush(color);
|
||||
painter.drawEllipse(0, 0, width(), height());
|
||||
}
|
||||
};
|
||||
|
@ -2350,7 +2350,7 @@ void game_list_frame::PopulateGameList()
|
||||
compat_item->setToolTip(game->compat.tooltip);
|
||||
if (!game->compat.color.isEmpty())
|
||||
{
|
||||
compat_item->setData(Qt::DecorationRole, compat_pixmap(game->compat.color, devicePixelRatioF() * 2));
|
||||
compat_item->setData(Qt::DecorationRole, gui::utils::circle_pixmap(game->compat.color, devicePixelRatioF() * 2));
|
||||
}
|
||||
|
||||
// Version
|
||||
|
@ -1,3 +1,8 @@
|
||||
#ifdef _WIN32
|
||||
// This is to avoid inclusion of winsock.h from windows.h header which creates conflicts with inclusion of winsock2.h later
|
||||
#define _WINSOCKAPI_
|
||||
#endif
|
||||
|
||||
#include "gui_application.h"
|
||||
|
||||
#include "qt_utils.h"
|
||||
@ -23,6 +28,8 @@
|
||||
#include "save_data_dialog.h"
|
||||
#include "msg_dialog_frame.h"
|
||||
#include "osk_dialog_frame.h"
|
||||
#include "recvmessage_dialog_frame.h"
|
||||
#include "sendmessage_dialog_frame.h"
|
||||
#include "stylesheets.h"
|
||||
|
||||
#include <QScreen>
|
||||
@ -346,6 +353,8 @@ void gui_application::InitializeCallbacks()
|
||||
callbacks.get_msg_dialog = [this]() -> std::shared_ptr<MsgDialogBase> { return m_show_gui ? std::make_shared<msg_dialog_frame>() : nullptr; };
|
||||
callbacks.get_osk_dialog = [this]() -> std::shared_ptr<OskDialogBase> { return m_show_gui ? std::make_shared<osk_dialog_frame>() : nullptr; };
|
||||
callbacks.get_save_dialog = []() -> std::unique_ptr<SaveDialogBase> { return std::make_unique<save_data_dialog>(); };
|
||||
callbacks.get_sendmessage_dialog = [this]() -> std::shared_ptr<SendMessageDialogBase> { return std::make_shared<sendmessage_dialog_frame>(); };
|
||||
callbacks.get_recvmessage_dialog = [this]() -> std::shared_ptr<RecvMessageDialogBase> { return std::make_shared<recvmessage_dialog_frame>(); };
|
||||
callbacks.get_trophy_notification_dialog = [this]() -> std::unique_ptr<TrophyNotificationBase> { return std::make_unique<trophy_notification_helper>(m_game_window); };
|
||||
|
||||
callbacks.on_run = [this](bool start_playtime) { OnEmulatorRun(start_playtime); };
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <QTableWidget>
|
||||
#include <QHeaderView>
|
||||
#include <QTreeWidgetItem>
|
||||
#include <QPainter>
|
||||
|
||||
#include <string>
|
||||
|
||||
@ -17,6 +18,23 @@ namespace gui
|
||||
{
|
||||
namespace utils
|
||||
{
|
||||
class circle_pixmap : public QPixmap
|
||||
{
|
||||
public:
|
||||
circle_pixmap(const QColor& color, qreal pixel_ratio)
|
||||
: QPixmap(pixel_ratio * 16, pixel_ratio * 16)
|
||||
{
|
||||
fill(Qt::transparent);
|
||||
|
||||
QPainter painter(this);
|
||||
setDevicePixelRatio(pixel_ratio);
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
painter.setPen(Qt::NoPen);
|
||||
painter.setBrush(color);
|
||||
painter.drawEllipse(0, 0, width(), height());
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
static QSet<T> list_to_set(const QList<T>& list)
|
||||
{
|
||||
|
125
rpcs3/rpcs3qt/recvmessage_dialog_frame.cpp
Normal file
125
rpcs3/rpcs3qt/recvmessage_dialog_frame.cpp
Normal file
@ -0,0 +1,125 @@
|
||||
#include <QVBoxLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <QPushButton>
|
||||
#include <QMessageBox>
|
||||
#include "recvmessage_dialog_frame.h"
|
||||
|
||||
#include "util/logs.hpp"
|
||||
|
||||
LOG_CHANNEL(recvmessage_dlg_log, "recvmessage dlg");
|
||||
|
||||
void recvmessage_callback(void* param, const std::shared_ptr<std::pair<std::string, message_data>> new_msg, u64 msg_id)
|
||||
{
|
||||
auto* dlg = static_cast<recvmessage_dialog_frame*>(param);
|
||||
dlg->callback_handler(std::move(new_msg), msg_id);
|
||||
}
|
||||
|
||||
recvmessage_dialog_frame::~recvmessage_dialog_frame()
|
||||
{
|
||||
if (m_dialog)
|
||||
{
|
||||
m_dialog->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
bool recvmessage_dialog_frame::Exec(SceNpBasicMessageMainType type, SceNpBasicMessageRecvOptions options, SceNpBasicMessageRecvAction& recv_result, u64& chosen_msg_id)
|
||||
{
|
||||
qRegisterMetaType<recvmessage_signal_struct>();
|
||||
|
||||
if (m_dialog)
|
||||
{
|
||||
m_dialog->close();
|
||||
delete m_dialog;
|
||||
}
|
||||
|
||||
m_dialog = new custom_dialog(false);
|
||||
m_dialog->setModal(true);
|
||||
|
||||
m_dialog->setWindowTitle(tr("Choose message:"));
|
||||
|
||||
m_rpcn = rpcn::rpcn_client::get_instance();
|
||||
|
||||
QVBoxLayout* vbox_global = new QVBoxLayout();
|
||||
|
||||
m_lst_messages = new QListWidget();
|
||||
vbox_global->addWidget(m_lst_messages);
|
||||
|
||||
QHBoxLayout* hbox_btns = new QHBoxLayout();
|
||||
hbox_btns->addStretch();
|
||||
QPushButton* btn_accept = new QPushButton(tr("Accept"));
|
||||
QPushButton* btn_deny = new QPushButton(tr("Deny"));
|
||||
QPushButton* btn_cancel = new QPushButton(tr("Cancel"));
|
||||
hbox_btns->addWidget(btn_accept);
|
||||
hbox_btns->addWidget(btn_deny);
|
||||
hbox_btns->addWidget(btn_cancel);
|
||||
vbox_global->addLayout(hbox_btns);
|
||||
|
||||
m_dialog->setLayout(vbox_global);
|
||||
|
||||
bool result = false;
|
||||
const bool preserve = options & SCE_NP_BASIC_RECV_MESSAGE_OPTIONS_PRESERVE;
|
||||
const bool include_bootable = options & SCE_NP_BASIC_RECV_MESSAGE_OPTIONS_INCLUDE_BOOTABLE;
|
||||
|
||||
auto accept_or_deny = [preserve, this, &result, &recv_result, &chosen_msg_id](SceNpBasicMessageRecvAction result_from_action)
|
||||
{
|
||||
auto selected = m_lst_messages->selectedItems();
|
||||
if (selected.empty())
|
||||
{
|
||||
QMessageBox::critical(m_dialog, tr("Error receiving a message!"), tr("You must select a message!"), QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
chosen_msg_id = selected[0]->data(Qt::UserRole).toULongLong();
|
||||
recv_result = result_from_action;
|
||||
result = true;
|
||||
|
||||
if (!preserve)
|
||||
{
|
||||
m_rpcn->discard_active_message(chosen_msg_id);
|
||||
}
|
||||
|
||||
m_dialog->close();
|
||||
};
|
||||
|
||||
connect(btn_accept, &QAbstractButton::clicked, this, [&accept_or_deny]()
|
||||
{ accept_or_deny(SCE_NP_BASIC_MESSAGE_ACTION_ACCEPT); });
|
||||
connect(btn_deny, &QAbstractButton::clicked, this, [&accept_or_deny]()
|
||||
{ accept_or_deny(SCE_NP_BASIC_MESSAGE_ACTION_DENY); });
|
||||
connect(this, &recvmessage_dialog_frame::signal_new_message, this, &recvmessage_dialog_frame::slot_new_message);
|
||||
|
||||
// Get list of messages
|
||||
const auto messages = m_rpcn->get_messages_and_register_cb(type, include_bootable, recvmessage_callback, this);
|
||||
for (const auto& message : messages)
|
||||
{
|
||||
add_message(message.second, message.first);
|
||||
}
|
||||
|
||||
m_dialog->exec();
|
||||
|
||||
m_rpcn->remove_message_cb(recvmessage_callback, this);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void recvmessage_dialog_frame::add_message(const std::shared_ptr<std::pair<std::string, message_data>>& msg, u64 msg_id)
|
||||
{
|
||||
ensure(msg);
|
||||
auto new_item = new QListWidgetItem(QString::fromStdString(msg->first));
|
||||
new_item->setData(Qt::UserRole, static_cast<qulonglong>(msg_id));
|
||||
m_lst_messages->addItem(new_item);
|
||||
}
|
||||
|
||||
void recvmessage_dialog_frame::slot_new_message(recvmessage_signal_struct msg_and_id)
|
||||
{
|
||||
add_message(msg_and_id.msg, msg_and_id.msg_id);
|
||||
}
|
||||
|
||||
void recvmessage_dialog_frame::callback_handler(std::shared_ptr<std::pair<std::string, message_data>> new_msg, u64 msg_id)
|
||||
{
|
||||
recvmessage_signal_struct signal_struct = {
|
||||
.msg = new_msg,
|
||||
.msg_id = msg_id,
|
||||
};
|
||||
|
||||
Q_EMIT signal_new_message(signal_struct);
|
||||
}
|
41
rpcs3/rpcs3qt/recvmessage_dialog_frame.h
Normal file
41
rpcs3/rpcs3qt/recvmessage_dialog_frame.h
Normal file
@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QListWidget>
|
||||
|
||||
#include "util/types.hpp"
|
||||
#include "custom_dialog.h"
|
||||
#include "Emu/NP/rpcn_client.h"
|
||||
|
||||
struct recvmessage_signal_struct
|
||||
{
|
||||
std::shared_ptr<std::pair<std::string, message_data>> msg;
|
||||
u64 msg_id;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(recvmessage_signal_struct);
|
||||
|
||||
class recvmessage_dialog_frame : public QObject, public RecvMessageDialogBase
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
recvmessage_dialog_frame() = default;
|
||||
~recvmessage_dialog_frame();
|
||||
bool Exec(SceNpBasicMessageMainType type, SceNpBasicMessageRecvOptions options, SceNpBasicMessageRecvAction& recv_result, u64& chosen_msg_id) override;
|
||||
void callback_handler(const std::shared_ptr<std::pair<std::string, message_data>> new_msg, u64 msg_id);
|
||||
|
||||
private:
|
||||
void add_message(const std::shared_ptr<std::pair<std::string, message_data>>& msg, u64 msg_id);
|
||||
|
||||
Q_SIGNALS:
|
||||
void signal_new_message(const recvmessage_signal_struct msg_and_id);
|
||||
|
||||
private Q_SLOTS:
|
||||
void slot_new_message(const recvmessage_signal_struct msg_and_id);
|
||||
|
||||
private:
|
||||
custom_dialog* m_dialog = nullptr;
|
||||
QListWidget* m_lst_messages = nullptr;
|
||||
std::shared_ptr<rpcn::rpcn_client> m_rpcn;
|
||||
};
|
@ -4,20 +4,90 @@
|
||||
#include <QPushButton>
|
||||
#include <QRegExpValidator>
|
||||
#include <QInputDialog>
|
||||
#include <QGroupBox>
|
||||
#include <QMenu>
|
||||
#include <thread>
|
||||
|
||||
#include "qt_utils.h"
|
||||
|
||||
#include "rpcn_settings_dialog.h"
|
||||
#include "Emu/NP/rpcn_config.h"
|
||||
#include "Emu/NP/rpcn_client.h"
|
||||
|
||||
#include <wolfssl/ssl.h>
|
||||
#include <wolfssl/openssl/evp.h>
|
||||
|
||||
rpcn_settings_dialog::rpcn_settings_dialog(QWidget* parent)
|
||||
: QDialog(parent)
|
||||
LOG_CHANNEL(rpcn_settings_log, "rpcn settings dlg");
|
||||
|
||||
const QString rpcn_state_to_qstr(rpcn::rpcn_state state)
|
||||
{
|
||||
setWindowTitle(tr("RPCN Configuration"));
|
||||
switch (state)
|
||||
{
|
||||
case rpcn::rpcn_state::failure_no_failure: return QObject::tr("No Error");
|
||||
case rpcn::rpcn_state::failure_input: return QObject::tr("Invalid Input");
|
||||
case rpcn::rpcn_state::failure_wolfssl: return QObject::tr("WolfSSL Error");
|
||||
case rpcn::rpcn_state::failure_resolve: return QObject::tr("Resolve Error");
|
||||
case rpcn::rpcn_state::failure_connect: return QObject::tr("Connect Error");
|
||||
case rpcn::rpcn_state::failure_id: return QObject::tr("Identification Error");
|
||||
case rpcn::rpcn_state::failure_id_already_logged_in: return QObject::tr("Identification Error: User Already Logged In");
|
||||
case rpcn::rpcn_state::failure_id_username: return QObject::tr("Identification Error: Invalid Username");
|
||||
case rpcn::rpcn_state::failure_id_password: return QObject::tr("Identification Error: Invalid Password");
|
||||
case rpcn::rpcn_state::failure_id_token: return QObject::tr("Identification Error: Invalid Token");
|
||||
case rpcn::rpcn_state::failure_protocol: return QObject::tr("Protocol Version Error");
|
||||
case rpcn::rpcn_state::failure_other: return QObject::tr("Unknown Error");
|
||||
default: return QObject::tr("Unhandled rpcn state!");
|
||||
}
|
||||
}
|
||||
|
||||
bool validate_rpcn_username(const std::string& input)
|
||||
{
|
||||
if (input.length() < 3 || input.length() > 16)
|
||||
return false;
|
||||
|
||||
return std::all_of(input.cbegin(), input.cend(), [](const char c)
|
||||
{ return std::isalnum(c) || c == '-' || c == '_'; });
|
||||
}
|
||||
|
||||
rpcn_settings_dialog::rpcn_settings_dialog(QWidget* parent)
|
||||
: QDialog(parent)
|
||||
{
|
||||
setWindowTitle(tr("RPCN"));
|
||||
setObjectName("rpcn_settings_dialog");
|
||||
setMinimumSize(QSize(400, 100));
|
||||
|
||||
QVBoxLayout* vbox_global = new QVBoxLayout();
|
||||
|
||||
QGroupBox* group_btns = new QGroupBox(tr("RPCN"));
|
||||
QHBoxLayout* hbox_group = new QHBoxLayout();
|
||||
|
||||
QPushButton* btn_account = new QPushButton(tr("Account"));
|
||||
QPushButton* btn_friends = new QPushButton(tr("Friends"));
|
||||
|
||||
hbox_group->addWidget(btn_account);
|
||||
hbox_group->addWidget(btn_friends);
|
||||
|
||||
group_btns->setLayout(hbox_group);
|
||||
vbox_global->addWidget(group_btns);
|
||||
setLayout(vbox_global);
|
||||
|
||||
connect(btn_account, &QPushButton::clicked, this, [this]()
|
||||
{
|
||||
rpcn_account_dialog dlg(this);
|
||||
dlg.exec();
|
||||
});
|
||||
|
||||
connect(btn_friends, &QPushButton::clicked, this, [this]()
|
||||
{
|
||||
rpcn_friends_dialog dlg(this);
|
||||
if (dlg.is_ok())
|
||||
dlg.exec();
|
||||
});
|
||||
}
|
||||
|
||||
rpcn_account_dialog::rpcn_account_dialog(QWidget* parent)
|
||||
: QDialog(parent)
|
||||
{
|
||||
setWindowTitle(tr("RPCN: Configuration"));
|
||||
setObjectName("rpcn_account_dialog");
|
||||
setMinimumSize(QSize(400, 200));
|
||||
|
||||
QVBoxLayout* vbox_global = new QVBoxLayout();
|
||||
@ -34,12 +104,16 @@ rpcn_settings_dialog::rpcn_settings_dialog(QWidget* parent)
|
||||
m_edit_npid->setValidator(new QRegExpValidator(QRegExp("^[a-zA-Z0-9_\\-]*$"), this));
|
||||
QLabel* label_pass = new QLabel(tr("Password:"));
|
||||
QPushButton* btn_chg_pass = new QPushButton(tr("Set Password"));
|
||||
QLabel *label_token = new QLabel(tr("Token:"));
|
||||
QLabel* label_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_save = new QPushButton(tr("Save"), this);
|
||||
QPushButton* btn_create = new QPushButton(tr("Create Account"), this);
|
||||
QPushButton* btn_resendtoken = new QPushButton(tr("Resend Token"), this);
|
||||
btn_resendtoken->setEnabled(false);
|
||||
QPushButton* btn_changepass = new QPushButton(tr("Change Password"), this);
|
||||
btn_changepass->setEnabled(false);
|
||||
QPushButton* btn_save = new QPushButton(tr("Save"), this);
|
||||
|
||||
vbox_labels->addWidget(label_host);
|
||||
vbox_labels->addWidget(label_npid);
|
||||
@ -52,6 +126,8 @@ rpcn_settings_dialog::rpcn_settings_dialog(QWidget* parent)
|
||||
vbox_edits->addWidget(m_edit_token);
|
||||
|
||||
hbox_buttons->addWidget(btn_create);
|
||||
hbox_buttons->addWidget(btn_resendtoken);
|
||||
hbox_buttons->addWidget(btn_changepass);
|
||||
hbox_buttons->addStretch();
|
||||
hbox_buttons->addWidget(btn_save);
|
||||
|
||||
@ -63,52 +139,43 @@ rpcn_settings_dialog::rpcn_settings_dialog(QWidget* parent)
|
||||
|
||||
setLayout(vbox_global);
|
||||
|
||||
connect(btn_chg_pass, &QAbstractButton::clicked, [this]()
|
||||
{
|
||||
QString password;
|
||||
|
||||
while (true)
|
||||
connect(btn_chg_pass, &QAbstractButton::clicked, this, [this]()
|
||||
{
|
||||
bool clicked_ok = false;
|
||||
password = QInputDialog::getText(this, "Set/Change Password", "Set your password", QLineEdit::Password, "", &clicked_ok);
|
||||
if (!clicked_ok)
|
||||
rpcn_ask_password_dialog ask_pass;
|
||||
ask_pass.exec();
|
||||
|
||||
auto password = ask_pass.get_password();
|
||||
if (!password)
|
||||
return;
|
||||
|
||||
if (password.isEmpty())
|
||||
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++)
|
||||
{
|
||||
QMessageBox::critical(this, tr("Wrong input"), tr("You need to enter a password!"), QMessageBox::Ok);
|
||||
constexpr auto pal = "0123456789abcdef";
|
||||
hash[i * 2] = pal[salted_pass[i] >> 4];
|
||||
hash[1 + i * 2] = pal[salted_pass[i] & 15];
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const std::string pass_str = password.toStdString();
|
||||
const std::string salt_str = "No matter where you go, everybody's connected.";
|
||||
g_cfg_rpcn.set_password(hash);
|
||||
g_cfg_rpcn.save();
|
||||
|
||||
u8 salted_pass[SHA_DIGEST_SIZE];
|
||||
QMessageBox::information(this, tr("RPCN Password Saved"), tr("Your password was saved successfully!"), QMessageBox::Ok);
|
||||
});
|
||||
|
||||
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++)
|
||||
connect(btn_save, &QAbstractButton::clicked, this, [this]()
|
||||
{
|
||||
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.save();
|
||||
});
|
||||
|
||||
connect(btn_save, &QAbstractButton::clicked, [this]()
|
||||
{
|
||||
if (this->save_config())
|
||||
this->close();
|
||||
});
|
||||
connect(btn_create, &QAbstractButton::clicked, [this]() { this->create_account(); });
|
||||
if (this->save_config())
|
||||
this->close();
|
||||
});
|
||||
connect(btn_create, &QAbstractButton::clicked, this, [this]()
|
||||
{ this->create_account(); });
|
||||
|
||||
g_cfg_rpcn.load();
|
||||
|
||||
@ -117,20 +184,12 @@ rpcn_settings_dialog::rpcn_settings_dialog(QWidget* parent)
|
||||
m_edit_token->setText(QString::fromStdString(g_cfg_rpcn.get_token()));
|
||||
}
|
||||
|
||||
bool rpcn_settings_dialog::save_config()
|
||||
bool rpcn_account_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();
|
||||
|
||||
auto validate = [](const std::string& input) -> bool
|
||||
{
|
||||
if (input.length() < 3 || input.length() > 16)
|
||||
return false;
|
||||
|
||||
return std::all_of(input.cbegin(), input.cend(), [](const char c) { return std::isalnum(c) || c == '-' || c == '_'; });
|
||||
};
|
||||
|
||||
if (host.empty())
|
||||
{
|
||||
QMessageBox::critical(this, tr("Missing host"), tr("You need to enter a host for rpcn!"), QMessageBox::Ok);
|
||||
@ -143,7 +202,7 @@ bool rpcn_settings_dialog::save_config()
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!validate(npid))
|
||||
if (!validate_rpcn_username(npid))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Invalid character"), tr("NPID must be between 3 and 16 characters and can only contain '-', '_' or alphanumeric characters."), QMessageBox::Ok);
|
||||
return false;
|
||||
@ -164,7 +223,7 @@ bool rpcn_settings_dialog::save_config()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool rpcn_settings_dialog::create_account()
|
||||
bool rpcn_account_dialog::create_account()
|
||||
{
|
||||
// Validate and save
|
||||
if (!save_config())
|
||||
@ -176,7 +235,7 @@ bool rpcn_settings_dialog::create_account()
|
||||
while (true)
|
||||
{
|
||||
bool clicked_ok = false;
|
||||
email = QInputDialog::getText(this, "Email address", "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);
|
||||
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 false;
|
||||
|
||||
@ -191,7 +250,7 @@ bool rpcn_settings_dialog::create_account()
|
||||
}
|
||||
}
|
||||
|
||||
const auto rpcn = std::make_shared<rpcn_client>(true);
|
||||
const auto rpcn = rpcn::rpcn_client::get_instance();
|
||||
|
||||
const auto host = g_cfg_rpcn.get_host();
|
||||
const auto npid = g_cfg_rpcn.get_npid();
|
||||
@ -199,32 +258,367 @@ bool rpcn_settings_dialog::create_account()
|
||||
const auto avatar_url = "https://rpcs3.net/cdn/netplay/DefaultAvatar.png";
|
||||
const auto password = g_cfg_rpcn.get_password();
|
||||
|
||||
std::thread(
|
||||
[](const std::shared_ptr<rpcn_client> rpcn)
|
||||
{
|
||||
while (rpcn.use_count() != 1)
|
||||
rpcn->manage_connection();
|
||||
|
||||
rpcn->disconnect();
|
||||
},
|
||||
rpcn)
|
||||
.detach();
|
||||
|
||||
if (!rpcn->connect(host))
|
||||
if (auto result = rpcn->wait_for_connection(); result != rpcn::rpcn_state::failure_no_failure)
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error Connecting"), tr("Failed to connect to RPCN server"), QMessageBox::Ok);
|
||||
rpcn->abort();
|
||||
const QString error_message = tr("Failed to connect to RPCN server:\n%0").arg(rpcn_state_to_qstr(result));
|
||||
QMessageBox::critical(this, tr("Error Connecting"), error_message, QMessageBox::Ok);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!rpcn->create_user(npid, password, online_name, avatar_url, email.toStdString()))
|
||||
if (auto error = rpcn->create_user(npid, password, online_name, avatar_url, email.toStdString()); error != rpcn::ErrorType::NoError)
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error Creating Account"), tr("Failed to create the account"), QMessageBox::Ok);
|
||||
rpcn->abort();
|
||||
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 false;
|
||||
}
|
||||
|
||||
QMessageBox::information(this, tr("Account created!"), tr("Your account has been created successfully!\nCheck your email for your token!"), QMessageBox::Ok);
|
||||
rpcn->abort();
|
||||
return true;
|
||||
}
|
||||
|
||||
rpcn_ask_password_dialog::rpcn_ask_password_dialog(QWidget* parent)
|
||||
: QDialog(parent)
|
||||
{
|
||||
QVBoxLayout* vbox_global = new QVBoxLayout();
|
||||
QHBoxLayout* hbox_buttons = new QHBoxLayout();
|
||||
|
||||
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);
|
||||
|
||||
QPushButton* btn_ok = new QPushButton(tr("Ok"));
|
||||
QPushButton* btn_cancel = new QPushButton(tr("Cancel"));
|
||||
|
||||
vbox_global->addWidget(label_pass1);
|
||||
vbox_global->addWidget(m_edit_pass1);
|
||||
vbox_global->addWidget(label_pass2);
|
||||
vbox_global->addWidget(m_edit_pass2);
|
||||
|
||||
hbox_buttons->addStretch();
|
||||
hbox_buttons->addWidget(btn_ok);
|
||||
hbox_buttons->addWidget(btn_cancel);
|
||||
|
||||
vbox_global->addLayout(hbox_buttons);
|
||||
|
||||
setLayout(vbox_global);
|
||||
|
||||
connect(btn_ok, &QAbstractButton::clicked, this, [this]()
|
||||
{
|
||||
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("Wrong input"), tr("You need to enter a password!"), QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
m_password = m_edit_pass1->text().toStdString();
|
||||
close();
|
||||
});
|
||||
connect(btn_cancel, &QAbstractButton::clicked, this, [this]()
|
||||
{ this->close(); });
|
||||
}
|
||||
|
||||
std::optional<std::string> rpcn_ask_password_dialog::get_password()
|
||||
{
|
||||
return m_password;
|
||||
}
|
||||
|
||||
void friend_callback(void* param, rpcn::NotificationType ntype, const std::string& username, bool status)
|
||||
{
|
||||
auto* dlg = static_cast<rpcn_friends_dialog*>(param);
|
||||
dlg->callback_handler(ntype, username, status);
|
||||
}
|
||||
|
||||
rpcn_friends_dialog::rpcn_friends_dialog(QWidget* parent)
|
||||
: QDialog(parent),
|
||||
m_green_icon(gui::utils::circle_pixmap(QColorConstants::Svg::green, devicePixelRatioF() * 2)),
|
||||
m_red_icon(gui::utils::circle_pixmap(QColorConstants::Svg::red, devicePixelRatioF() * 2)),
|
||||
m_yellow_icon(gui::utils::circle_pixmap(QColorConstants::Svg::yellow, devicePixelRatioF() * 2)),
|
||||
m_orange_icon(gui::utils::circle_pixmap(QColorConstants::Svg::orange, devicePixelRatioF() * 2)),
|
||||
m_black_icon(gui::utils::circle_pixmap(QColorConstants::Svg::black, devicePixelRatioF() * 2))
|
||||
{
|
||||
setWindowTitle(tr("RPCN: Friends"));
|
||||
setObjectName("rpcn_friends_dialog");
|
||||
setMinimumSize(QSize(400, 100));
|
||||
|
||||
QVBoxLayout* vbox_global = new QVBoxLayout();
|
||||
|
||||
QHBoxLayout* hbox_groupboxes = new QHBoxLayout();
|
||||
|
||||
QGroupBox* grp_list_friends = new QGroupBox(tr("Friends"));
|
||||
QVBoxLayout* vbox_lst_friends = new QVBoxLayout();
|
||||
m_lst_friends = new QListWidget(this);
|
||||
m_lst_friends->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
vbox_lst_friends->addWidget(m_lst_friends);
|
||||
QPushButton* btn_addfriend = new QPushButton(tr("Add Friend"));
|
||||
vbox_lst_friends->addWidget(btn_addfriend);
|
||||
grp_list_friends->setLayout(vbox_lst_friends);
|
||||
hbox_groupboxes->addWidget(grp_list_friends);
|
||||
|
||||
QGroupBox* grp_list_requests = new QGroupBox(tr("Friend Requests"));
|
||||
QVBoxLayout* vbox_lst_requests = new QVBoxLayout();
|
||||
m_lst_requests = new QListWidget(this);
|
||||
m_lst_requests->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
vbox_lst_requests->addWidget(m_lst_requests);
|
||||
QHBoxLayout* hbox_request_btns = new QHBoxLayout();
|
||||
vbox_lst_requests->addLayout(hbox_request_btns);
|
||||
grp_list_requests->setLayout(vbox_lst_requests);
|
||||
hbox_groupboxes->addWidget(grp_list_requests);
|
||||
|
||||
QGroupBox* grp_list_blocks = new QGroupBox(tr("Blocked Users"));
|
||||
QVBoxLayout* vbox_lst_blocks = new QVBoxLayout();
|
||||
m_lst_blocks = new QListWidget(this);
|
||||
vbox_lst_blocks->addWidget(m_lst_blocks);
|
||||
grp_list_blocks->setLayout(vbox_lst_blocks);
|
||||
hbox_groupboxes->addWidget(grp_list_blocks);
|
||||
|
||||
vbox_global->addLayout(hbox_groupboxes);
|
||||
|
||||
setLayout(vbox_global);
|
||||
|
||||
// Tries to connect to RPCN
|
||||
m_rpcn = rpcn::rpcn_client::get_instance();
|
||||
|
||||
if (auto res = m_rpcn->wait_for_connection(); res != rpcn::rpcn_state::failure_no_failure)
|
||||
{
|
||||
const QString error_msg = tr("Failed to connect to RPCN:\n%0").arg(rpcn_state_to_qstr(res));
|
||||
QMessageBox::warning(parent, tr("Error connecting to RPCN!"), error_msg, QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
if (auto res = m_rpcn->wait_for_authentified(); res != rpcn::rpcn_state::failure_no_failure)
|
||||
{
|
||||
const QString error_msg = tr("Failed to authentify to RPCN:\n%0").arg(rpcn_state_to_qstr(res));
|
||||
QMessageBox::warning(parent, tr("Error authentifying to RPCN!"), error_msg, QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get friends, setup callback and setup comboboxes
|
||||
rpcn::friend_data data;
|
||||
m_rpcn->get_friends_and_register_cb(data, friend_callback, this);
|
||||
|
||||
for (const auto& fr : data.friends)
|
||||
{
|
||||
add_update_list(m_lst_friends, QString::fromStdString(fr.first), fr.second.first ? m_green_icon : m_red_icon, fr.second.first);
|
||||
}
|
||||
|
||||
for (const auto& fr_req : data.requests_sent)
|
||||
{
|
||||
add_update_list(m_lst_requests, QString::fromStdString(fr_req), m_orange_icon, QVariant(false));
|
||||
}
|
||||
|
||||
for (const auto& fr_req : data.requests_received)
|
||||
{
|
||||
add_update_list(m_lst_requests, QString::fromStdString(fr_req), m_yellow_icon, QVariant(true));
|
||||
}
|
||||
|
||||
for (const auto& blck : data.blocked)
|
||||
{
|
||||
add_update_list(m_lst_blocks, QString::fromStdString(blck), m_red_icon, QVariant(false));
|
||||
}
|
||||
|
||||
connect(this, &rpcn_friends_dialog::signal_add_update_friend, this, &rpcn_friends_dialog::add_update_friend);
|
||||
connect(this, &rpcn_friends_dialog::signal_remove_friend, this, &rpcn_friends_dialog::remove_friend);
|
||||
connect(this, &rpcn_friends_dialog::signal_add_query, this, &rpcn_friends_dialog::add_query);
|
||||
|
||||
connect(m_lst_friends, &QListWidget::customContextMenuRequested, this, [this](const QPoint& pos)
|
||||
{
|
||||
if (!m_lst_friends->itemAt(pos) || m_lst_friends->selectedItems().count() != 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
QListWidgetItem* selected_item = m_lst_friends->selectedItems().first();
|
||||
std::string str_sel_friend = selected_item->text().toStdString();
|
||||
|
||||
QMenu* context_menu = new QMenu();
|
||||
QAction* remove_friend_action = context_menu->addAction(tr("&Remove Friend"));
|
||||
|
||||
connect(remove_friend_action, &QAction::triggered, this, [this, str_sel_friend]()
|
||||
{
|
||||
if (!m_rpcn->remove_friend(str_sel_friend))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error removing a friend!"), tr("An error occured trying to remove a friend!"), QMessageBox::Ok);
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::information(this, tr("Friend removed!"), tr("You've successfully removed a friend!"), QMessageBox::Ok);
|
||||
}
|
||||
});
|
||||
|
||||
context_menu->exec(m_lst_friends->viewport()->mapToGlobal(pos));
|
||||
context_menu->deleteLater();
|
||||
});
|
||||
|
||||
connect(m_lst_requests, &QListWidget::customContextMenuRequested, this, [this](const QPoint& pos)
|
||||
{
|
||||
if (!m_lst_requests->itemAt(pos) || m_lst_requests->selectedItems().count() != 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
QListWidgetItem* selected_item = m_lst_requests->selectedItems().first();
|
||||
|
||||
// Only create context menu for incoming requests
|
||||
if (selected_item->data(Qt::UserRole) == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::string str_sel_friend = selected_item->text().toStdString();
|
||||
|
||||
QMenu* context_menu = new QMenu();
|
||||
QAction* remove_friend_action = context_menu->addAction(tr("&Accept Request"));
|
||||
|
||||
connect(remove_friend_action, &QAction::triggered, this, [this, str_sel_friend]()
|
||||
{
|
||||
if (!m_rpcn->add_friend(str_sel_friend))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error adding a friend!"), tr("An error occured trying to add a friend!"), QMessageBox::Ok);
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::information(this, tr("Friend added!"), tr("You've successfully added a friend!"), QMessageBox::Ok);
|
||||
}
|
||||
});
|
||||
|
||||
context_menu->exec(m_lst_requests->viewport()->mapToGlobal(pos));
|
||||
context_menu->deleteLater();
|
||||
});
|
||||
|
||||
connect(btn_addfriend, &QAbstractButton::clicked, this, [this]()
|
||||
{
|
||||
std::string str_friend_username;
|
||||
while (true)
|
||||
{
|
||||
bool ok = false;
|
||||
QString friend_username = QInputDialog::getText(this, tr("Add a friend"), tr("Friend's username:"), QLineEdit::Normal, "", &ok);
|
||||
if (!ok)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
str_friend_username = friend_username.toStdString();
|
||||
|
||||
if (validate_rpcn_username(str_friend_username))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
QMessageBox::critical(this, tr("Error validating username"), tr("The username you entered is invalid"), QMessageBox::Ok);
|
||||
}
|
||||
|
||||
if (!m_rpcn->add_friend(str_friend_username))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error adding friend"), tr("An error occured adding friend"), QMessageBox::Ok);
|
||||
}
|
||||
else
|
||||
{
|
||||
add_update_list(m_lst_requests, QString::fromStdString(str_friend_username), m_orange_icon, QVariant(false));
|
||||
QMessageBox::information(this, tr("Friend added"), tr("Friend was successfully added!"), QMessageBox::Ok);
|
||||
}
|
||||
});
|
||||
|
||||
m_rpcn_ok = true;
|
||||
}
|
||||
|
||||
rpcn_friends_dialog::~rpcn_friends_dialog()
|
||||
{
|
||||
m_rpcn->remove_friend_cb(friend_callback, this);
|
||||
}
|
||||
|
||||
bool rpcn_friends_dialog::is_ok() const
|
||||
{
|
||||
return m_rpcn_ok;
|
||||
}
|
||||
|
||||
void rpcn_friends_dialog::add_update_list(QListWidget* list, const QString& name, const QIcon& icon, const QVariant& data)
|
||||
{
|
||||
QListWidgetItem* item = nullptr;
|
||||
if (auto found = list->findItems(name, Qt::MatchExactly); !found.empty())
|
||||
{
|
||||
item = found[0];
|
||||
item->setData(Qt::UserRole, data);
|
||||
item->setIcon(icon);
|
||||
}
|
||||
else
|
||||
{
|
||||
item = new QListWidgetItem(name);
|
||||
item->setIcon(icon);
|
||||
item->setData(Qt::UserRole, data);
|
||||
list->addItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
void rpcn_friends_dialog::remove_list(QListWidget* list, const QString& name)
|
||||
{
|
||||
if (auto found = list->findItems(name, Qt::MatchExactly); !found.empty())
|
||||
{
|
||||
delete list->takeItem(list->row(found[0]));
|
||||
}
|
||||
}
|
||||
|
||||
void rpcn_friends_dialog::add_update_friend(QString name, bool status)
|
||||
{
|
||||
add_update_list(m_lst_friends, name, status ? m_green_icon : m_red_icon, status);
|
||||
remove_list(m_lst_requests, name);
|
||||
}
|
||||
|
||||
void rpcn_friends_dialog::remove_friend(QString name)
|
||||
{
|
||||
remove_list(m_lst_friends, name);
|
||||
remove_list(m_lst_requests, name);
|
||||
}
|
||||
|
||||
void rpcn_friends_dialog::add_query(QString name)
|
||||
{
|
||||
add_update_list(m_lst_requests, name, m_yellow_icon, QVariant(true));
|
||||
}
|
||||
|
||||
void rpcn_friends_dialog::callback_handler(rpcn::NotificationType ntype, std::string username, bool status)
|
||||
{
|
||||
QString qtr_username = QString::fromStdString(username);
|
||||
switch (ntype)
|
||||
{
|
||||
case rpcn::NotificationType::FriendQuery: // Other user sent a friend request
|
||||
{
|
||||
Q_EMIT signal_add_query(qtr_username);
|
||||
break;
|
||||
}
|
||||
case rpcn::NotificationType::FriendNew: // Add a friend to the friendlist(either accepted a friend request or friend accepted it)
|
||||
{
|
||||
Q_EMIT signal_add_update_friend(qtr_username, status);
|
||||
break;
|
||||
}
|
||||
case rpcn::NotificationType::FriendLost: // Remove friend from the friendlist(user removed friend or friend removed friend)
|
||||
{
|
||||
Q_EMIT signal_remove_friend(qtr_username);
|
||||
break;
|
||||
}
|
||||
case rpcn::NotificationType::FriendStatus: // Set status of friend to Offline or Online
|
||||
{
|
||||
Q_EMIT signal_add_update_friend(qtr_username, status);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
rpcn_settings_log.fatal("An unhandled notification type was received by the rpcn friends dialog callback!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include <QDialog>
|
||||
#include <QLineEdit>
|
||||
#include <QListWidget>
|
||||
|
||||
#include "Emu/NP/rpcn_client.h"
|
||||
|
||||
class rpcn_settings_dialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
rpcn_settings_dialog(QWidget* parent = nullptr);
|
||||
};
|
||||
|
||||
class rpcn_account_dialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
rpcn_account_dialog(QWidget* parent = nullptr);
|
||||
|
||||
bool save_config();
|
||||
bool create_account();
|
||||
@ -16,3 +27,51 @@ public:
|
||||
protected:
|
||||
QLineEdit *m_edit_host, *m_edit_npid, *m_edit_token;
|
||||
};
|
||||
|
||||
class rpcn_ask_password_dialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
rpcn_ask_password_dialog(QWidget* parent = nullptr);
|
||||
std::optional<std::string> get_password();
|
||||
|
||||
private:
|
||||
QLineEdit *m_edit_pass1, *m_edit_pass2;
|
||||
std::optional<std::string> m_password;
|
||||
};
|
||||
|
||||
class rpcn_friends_dialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
rpcn_friends_dialog(QWidget* parent = nullptr);
|
||||
~rpcn_friends_dialog();
|
||||
void callback_handler(rpcn::NotificationType ntype, std::string username, bool status);
|
||||
bool is_ok() const;
|
||||
|
||||
private:
|
||||
void add_update_list(QListWidget* list, const QString& name, const QIcon& icon, const QVariant& data);
|
||||
void remove_list(QListWidget* list, const QString& name);
|
||||
|
||||
private Q_SLOTS:
|
||||
void add_update_friend(QString name, bool status);
|
||||
void remove_friend(QString name);
|
||||
void add_query(QString name);
|
||||
|
||||
Q_SIGNALS:
|
||||
void signal_add_update_friend(QString name, bool status);
|
||||
void signal_remove_friend(QString name);
|
||||
void signal_add_query(QString name);
|
||||
|
||||
private:
|
||||
const QIcon m_green_icon, m_red_icon, m_yellow_icon, m_orange_icon, m_black_icon;
|
||||
// list of friends
|
||||
QListWidget* m_lst_friends = nullptr;
|
||||
// list of friend requests sent by/to the current user
|
||||
QListWidget* m_lst_requests = nullptr;
|
||||
// list of people blocked by the user
|
||||
QListWidget* m_lst_blocks = nullptr;
|
||||
|
||||
std::shared_ptr<rpcn::rpcn_client> m_rpcn;
|
||||
bool m_rpcn_ok = false;
|
||||
};
|
||||
|
164
rpcs3/rpcs3qt/sendmessage_dialog_frame.cpp
Normal file
164
rpcs3/rpcs3qt/sendmessage_dialog_frame.cpp
Normal file
@ -0,0 +1,164 @@
|
||||
#include <QVBoxLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <QPushButton>
|
||||
#include <QMessageBox>
|
||||
#include "sendmessage_dialog_frame.h"
|
||||
|
||||
#include "util/logs.hpp"
|
||||
|
||||
LOG_CHANNEL(sendmessage_dlg_log, "sendmessage dlg");
|
||||
|
||||
void sendmessage_friend_callback(void* param, rpcn::NotificationType ntype, const std::string& username, bool status)
|
||||
{
|
||||
auto* dlg = static_cast<sendmessage_dialog_frame*>(param);
|
||||
dlg->callback_handler(ntype, username, status);
|
||||
}
|
||||
|
||||
sendmessage_dialog_frame::~sendmessage_dialog_frame()
|
||||
{
|
||||
if (m_dialog)
|
||||
{
|
||||
m_dialog->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
bool sendmessage_dialog_frame::Exec(message_data& msg_data, std::set<std::string>& npids)
|
||||
{
|
||||
if (m_dialog)
|
||||
{
|
||||
m_dialog->close();
|
||||
delete m_dialog;
|
||||
}
|
||||
|
||||
m_dialog = new custom_dialog(false);
|
||||
m_dialog->setModal(true);
|
||||
|
||||
m_dialog->setWindowTitle(tr("Choose friend to message:"));
|
||||
|
||||
m_rpcn = rpcn::rpcn_client::get_instance();
|
||||
|
||||
QVBoxLayout* vbox_global = new QVBoxLayout();
|
||||
|
||||
m_lst_friends = new QListWidget();
|
||||
vbox_global->addWidget(m_lst_friends);
|
||||
|
||||
QHBoxLayout* hbox_btns = new QHBoxLayout();
|
||||
hbox_btns->addStretch();
|
||||
QPushButton* btn_ok = new QPushButton(tr("Ok"));
|
||||
QPushButton* btn_cancel = new QPushButton(tr("Cancel"));
|
||||
hbox_btns->addWidget(btn_ok);
|
||||
hbox_btns->addWidget(btn_cancel);
|
||||
vbox_global->addLayout(hbox_btns);
|
||||
|
||||
m_dialog->setLayout(vbox_global);
|
||||
|
||||
connect(this, &sendmessage_dialog_frame::signal_add_friend, this, &sendmessage_dialog_frame::slot_add_friend);
|
||||
connect(this, &sendmessage_dialog_frame::signal_remove_friend, this, &sendmessage_dialog_frame::slot_remove_friend);
|
||||
|
||||
bool result = false;
|
||||
|
||||
connect(btn_ok, &QAbstractButton::clicked, this, [this, &msg_data, &npids, &result]()
|
||||
{
|
||||
// Check one target is selected
|
||||
auto selected = m_lst_friends->selectedItems();
|
||||
if (selected.empty())
|
||||
{
|
||||
QMessageBox::critical(m_dialog, tr("Error sending a message!"), tr("You must select a friend!"), QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
npids.insert(selected[0]->text().toStdString());
|
||||
|
||||
// Send the message
|
||||
result = m_rpcn->sendmessage(msg_data, npids);
|
||||
m_dialog->close();
|
||||
});
|
||||
|
||||
connect(btn_cancel, &QAbstractButton::clicked, m_dialog, &custom_dialog::close);
|
||||
|
||||
rpcn::friend_data data;
|
||||
m_rpcn->get_friends_and_register_cb(data, sendmessage_friend_callback, this);
|
||||
|
||||
for (const auto& fr : data.friends)
|
||||
{
|
||||
// Only add online friends to the list
|
||||
if (fr.second.first)
|
||||
{
|
||||
add_friend(m_lst_friends, QString::fromStdString(fr.first));
|
||||
}
|
||||
}
|
||||
|
||||
m_dialog->exec();
|
||||
|
||||
m_rpcn->remove_friend_cb(sendmessage_friend_callback, this);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void sendmessage_dialog_frame::add_friend(QListWidget* list, const QString& name)
|
||||
{
|
||||
if (auto found = list->findItems(name, Qt::MatchExactly); !found.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
list->addItem(new QListWidgetItem(name));
|
||||
}
|
||||
|
||||
void sendmessage_dialog_frame::remove_friend(QListWidget* list, const QString& name)
|
||||
{
|
||||
if (auto found = list->findItems(name, Qt::MatchExactly); !found.empty())
|
||||
{
|
||||
delete list->takeItem(list->row(found[0]));
|
||||
}
|
||||
}
|
||||
|
||||
void sendmessage_dialog_frame::slot_add_friend(QString name)
|
||||
{
|
||||
add_friend(m_lst_friends, name);
|
||||
}
|
||||
|
||||
void sendmessage_dialog_frame::slot_remove_friend(QString name)
|
||||
{
|
||||
remove_friend(m_lst_friends, name);
|
||||
}
|
||||
|
||||
void sendmessage_dialog_frame::callback_handler(rpcn::NotificationType ntype, const std::string& username, bool status)
|
||||
{
|
||||
QString qtr_username = QString::fromStdString(username);
|
||||
switch (ntype)
|
||||
{
|
||||
case rpcn::NotificationType::FriendQuery: // Other user sent a friend request
|
||||
break;
|
||||
case rpcn::NotificationType::FriendNew: // Add a friend to the friendlist(either accepted a friend request or friend accepted it)
|
||||
{
|
||||
if (status)
|
||||
{
|
||||
Q_EMIT signal_add_friend(qtr_username);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case rpcn::NotificationType::FriendLost: // Remove friend from the friendlist(user removed friend or friend removed friend)
|
||||
{
|
||||
Q_EMIT signal_remove_friend(qtr_username);
|
||||
break;
|
||||
}
|
||||
case rpcn::NotificationType::FriendStatus: // Set status of friend to Offline or Online
|
||||
{
|
||||
if (status)
|
||||
{
|
||||
Q_EMIT signal_add_friend(qtr_username);
|
||||
}
|
||||
else
|
||||
{
|
||||
Q_EMIT signal_remove_friend(qtr_username);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
sendmessage_dlg_log.fatal("An unhandled notification type was received by the sendmessage dialog callback!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
37
rpcs3/rpcs3qt/sendmessage_dialog_frame.h
Normal file
37
rpcs3/rpcs3qt/sendmessage_dialog_frame.h
Normal file
@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QListWidget>
|
||||
|
||||
#include "util/types.hpp"
|
||||
#include "custom_dialog.h"
|
||||
#include "Emu/NP/rpcn_client.h"
|
||||
|
||||
class sendmessage_dialog_frame : public QObject, public SendMessageDialogBase
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
sendmessage_dialog_frame() = default;
|
||||
~sendmessage_dialog_frame();
|
||||
bool Exec(message_data& msg_data, std::set<std::string>& npids) override;
|
||||
void callback_handler(rpcn::NotificationType ntype, const std::string& username, bool status);
|
||||
|
||||
private:
|
||||
void add_friend(QListWidget* list, const QString& name);
|
||||
void remove_friend(QListWidget* list, const QString& name);
|
||||
|
||||
private:
|
||||
custom_dialog* m_dialog = nullptr;
|
||||
QListWidget* m_lst_friends = nullptr;
|
||||
|
||||
std::shared_ptr<rpcn::rpcn_client> m_rpcn;
|
||||
|
||||
Q_SIGNALS:
|
||||
void signal_add_friend(QString name);
|
||||
void signal_remove_friend(QString name);
|
||||
|
||||
private Q_SLOTS:
|
||||
void slot_add_friend(QString name);
|
||||
void slot_remove_friend(QString name);
|
||||
};
|
Loading…
Reference in New Issue
Block a user