mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 10:42:36 +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)
|
# TODO(cjj19970505@live.cn)
|
||||||
# OPENSSL_EXTRA, WOLFSSL_DES_ECB and HAVE_SNI are unconfigurable from CMake cache.
|
# 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)
|
# 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_TLS13 "no" CACHE INTERNAL "")
|
||||||
set(WOLFSSL_SHA224 "yes" 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>
|
<ClCompile>
|
||||||
<Optimization>Disabled</Optimization>
|
<Optimization>Disabled</Optimization>
|
||||||
<AdditionalIncludeDirectories>./wolfssl;./wolfssl/IDE/WIN;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<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>
|
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||||
<PrecompiledHeader>
|
<PrecompiledHeader>
|
||||||
</PrecompiledHeader>
|
</PrecompiledHeader>
|
||||||
@ -62,7 +62,7 @@
|
|||||||
<Optimization>MaxSpeed</Optimization>
|
<Optimization>MaxSpeed</Optimization>
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
<AdditionalIncludeDirectories>./wolfssl;./wolfssl/IDE/WIN;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<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>
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
<PrecompiledHeader>
|
<PrecompiledHeader>
|
||||||
</PrecompiledHeader>
|
</PrecompiledHeader>
|
||||||
|
@ -110,6 +110,15 @@ error_code cellSysutilAvc2StartVoiceDetection()
|
|||||||
error_code cellSysutilAvc2UnloadAsync()
|
error_code cellSysutilAvc2UnloadAsync()
|
||||||
{
|
{
|
||||||
cellSysutilAvc2.todo("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;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
#include "Emu/system_utils.hpp"
|
#include "Emu/system_utils.hpp"
|
||||||
#include "Emu/VFS.h"
|
#include "Emu/VFS.h"
|
||||||
#include "Emu/Cell/PPUModule.h"
|
#include "Emu/Cell/PPUModule.h"
|
||||||
|
#include "Emu/Io/interception.h"
|
||||||
|
#include "Utilities/StrUtil.h"
|
||||||
|
|
||||||
#include "sysPrxForUser.h"
|
#include "sysPrxForUser.h"
|
||||||
#include "Emu/IdManager.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)
|
error_code sceNpInit(u32 poolsize, vm::ptr<void> poolptr)
|
||||||
{
|
{
|
||||||
sceNp.warning("sceNpInit(poolsize=0x%x, poolptr=*0x%x)", poolsize, 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)
|
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>>();
|
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;
|
return SCE_NP_BASIC_ERROR_NOT_INITIALIZED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (nph.basic_handler.registered)
|
||||||
|
{
|
||||||
|
return SCE_NP_BASIC_ERROR_EXCEEDS_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
if (!context || !handler)
|
if (!context || !handler)
|
||||||
{
|
{
|
||||||
return SCE_NP_BASIC_ERROR_INVALID_ARGUMENT;
|
return SCE_NP_BASIC_ERROR_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
nph.basic_handler = handler;
|
memcpy(&nph.basic_handler.context, context.get_ptr(), sizeof(nph.basic_handler.context));
|
||||||
nph.basic_handler_arg = arg;
|
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;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
@ -660,11 +675,22 @@ error_code sceNpBasicRegisterContextSensitiveHandler(vm::cptr<SceNpCommunication
|
|||||||
return SCE_NP_BASIC_ERROR_NOT_INITIALIZED;
|
return SCE_NP_BASIC_ERROR_NOT_INITIALIZED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (nph.basic_handler.registered)
|
||||||
|
{
|
||||||
|
return SCE_NP_BASIC_ERROR_EXCEEDS_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
if (!context || !handler)
|
if (!context || !handler)
|
||||||
{
|
{
|
||||||
return SCE_NP_BASIC_ERROR_INVALID_ARGUMENT;
|
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;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -679,6 +705,13 @@ error_code sceNpBasicUnregisterHandler()
|
|||||||
return SCE_NP_BASIC_ERROR_NOT_INITIALIZED;
|
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;
|
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)
|
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>>();
|
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;
|
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;
|
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);
|
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;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -845,9 +971,9 @@ error_code sceNpBasicRecvMessageAttachment(sys_memory_container_t containerId)
|
|||||||
return CELL_OK;
|
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>>();
|
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;
|
return SCE_NP_BASIC_ERROR_NOT_INITIALIZED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!nph.basic_handler.registered)
|
||||||
|
{
|
||||||
|
return SCE_NP_BASIC_ERROR_NOT_REGISTERED;
|
||||||
|
}
|
||||||
|
|
||||||
if (!buffer || !size)
|
if (!buffer || !size)
|
||||||
{
|
{
|
||||||
return SCE_NP_BASIC_ERROR_INVALID_ARGUMENT;
|
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;
|
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;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
error_code sceNpBasicRecvMessageCustom(u16 mainType, u32 recvOptions, sys_memory_container_t containerId)
|
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>>();
|
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;
|
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;
|
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;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -972,8 +1172,7 @@ error_code sceNpBasicGetFriendListEntryCount(vm::ptr<u32> count)
|
|||||||
return SCE_NP_ERROR_ID_NOT_FOUND;
|
return SCE_NP_ERROR_ID_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Check if there are any friends
|
*count = nph.get_num_friends();
|
||||||
*count = 0;
|
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
@ -1258,7 +1457,7 @@ error_code sceNpBasicGetBlockListEntryCount(vm::ptr<u32> count)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Check if there are block lists
|
// TODO: Check if there are block lists
|
||||||
*count = 0;
|
*count = nph.get_num_blocks();
|
||||||
|
|
||||||
return CELL_OK;
|
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;
|
return SCE_NP_BASIC_ERROR_NOT_INITIALIZED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!nph.basic_handler.registered)
|
||||||
|
{
|
||||||
|
return SCE_NP_BASIC_ERROR_NOT_REGISTERED;
|
||||||
|
}
|
||||||
|
|
||||||
if (!event || !from || !data || !size)
|
if (!event || !from || !data || !size)
|
||||||
{
|
{
|
||||||
return SCE_NP_BASIC_ERROR_INVALID_ARGUMENT;
|
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
|
//*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)
|
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();
|
const auto& ticket = nph.get_ticket();
|
||||||
|
*bufferSize = static_cast<u32>(ticket.size());
|
||||||
|
|
||||||
if (!buffer)
|
if (!buffer)
|
||||||
{
|
{
|
||||||
*bufferSize = static_cast<u32>(ticket.size());
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
#include "cellRtc.h"
|
#include "cellRtc.h"
|
||||||
#include "Emu/Cell/ErrorCodes.h"
|
#include "Emu/Cell/ErrorCodes.h"
|
||||||
|
|
||||||
|
#include <set>
|
||||||
|
|
||||||
error_code sceNpInit(u32 poolsize, vm::ptr<void> poolptr);
|
error_code sceNpInit(u32 poolsize, vm::ptr<void> poolptr);
|
||||||
error_code sceNpTerm();
|
error_code sceNpTerm();
|
||||||
|
|
||||||
@ -1022,11 +1024,11 @@ struct SceNpBasicMessageDetails
|
|||||||
be_t<u16> mainType;
|
be_t<u16> mainType;
|
||||||
be_t<u16> subType;
|
be_t<u16> subType;
|
||||||
be_t<u32> msgFeatures;
|
be_t<u32> msgFeatures;
|
||||||
const SceNpId npids;
|
vm::bptr<SceNpId> npids;
|
||||||
be_t<u32> count;
|
be_t<u32> count;
|
||||||
const s8 subject;
|
vm::bptr<char> subject;
|
||||||
const s8 body;
|
vm::bptr<char> body;
|
||||||
const be_t<u32> data;
|
vm::bptr<u8> data;
|
||||||
be_t<u32> size;
|
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 SceNpProfileResultHandler = s32(s32 result, vm::ptr<void> arg);
|
||||||
|
|
||||||
using SceNpManagerSubSigninCallback = void(s32 result, vm::ptr<SceNpId> npId, vm::ptr<void> cb_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)
|
switch (code)
|
||||||
{
|
{
|
||||||
case 1:
|
case SCE_NP_SIGNALING_CONN_INFO_RTT:
|
||||||
{
|
{
|
||||||
connInfo->rtt = 20000; // HACK
|
connInfo->rtt = 20000; // HACK
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 2:
|
case SCE_NP_SIGNALING_CONN_INFO_BANDWIDTH:
|
||||||
{
|
{
|
||||||
connInfo->bandwidth = 10'000'000; // 10 MBPS HACK
|
connInfo->bandwidth = 10'000'000; // 10 MBPS HACK
|
||||||
break;
|
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>>();
|
auto& sigh = g_fxo->get<named_thread<signaling_handler>>();
|
||||||
const auto si = sigh.get_sig2_infos(roomId, memberId);
|
const auto si = sigh.get_sig2_infos(roomId, memberId);
|
||||||
@ -631,7 +637,15 @@ error_code sceNpMatching2SignalingGetConnectionInfo(
|
|||||||
connInfo->address.addr.np_s_addr = si.addr;
|
connInfo->address.addr.np_s_addr = si.addr;
|
||||||
break;
|
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
|
connInfo->packet_loss = 1; // HACK
|
||||||
break;
|
break;
|
||||||
@ -1274,6 +1288,8 @@ error_code sceNpMatching2GetRoomDataExternalList(
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*assignedReqId = nph.get_roomdata_external_list(ctxId, optParam, reqParam.get_ptr());
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -978,7 +978,7 @@ struct network_thread
|
|||||||
WSADATA wsa_data;
|
WSADATA wsa_data;
|
||||||
WSAStartup(MAKEWORD(2, 2), &wsa_data);
|
WSAStartup(MAKEWORD(2, 2), &wsa_data);
|
||||||
#endif
|
#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));
|
list_p2p_ports.emplace(std::piecewise_construct, std::forward_as_tuple(3658), std::forward_as_tuple(3658));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,32 +55,8 @@ 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)
|
||||||
{
|
{
|
||||||
search_resp->range.size = resp->size();
|
|
||||||
search_resp->range.startIndex = resp->startIndex();
|
|
||||||
search_resp->range.total = resp->total();
|
|
||||||
|
|
||||||
if (resp->rooms() && resp->rooms()->size() != 0)
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
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
|
|
||||||
{
|
|
||||||
search_resp->roomDataExternal = room_info;
|
|
||||||
}
|
|
||||||
|
|
||||||
previous_next = vm::cast(room_info.addr());
|
|
||||||
|
|
||||||
room_info->serverId = room->serverId();
|
room_info->serverId = room->serverId();
|
||||||
room_info->worldId = room->worldId();
|
room_info->worldId = room->worldId();
|
||||||
room_info->publicSlotNum = room->publicSlotNum();
|
room_info->publicSlotNum = room->publicSlotNum();
|
||||||
@ -91,7 +67,8 @@ void np_handler::SearchRoomReponse_to_SceNpMatching2SearchRoomResponse(const Sea
|
|||||||
room_info->maxSlot = room->maxSlot();
|
room_info->maxSlot = room->maxSlot();
|
||||||
room_info->openPrivateSlotNum = room->openPrivateSlotNum();
|
room_info->openPrivateSlotNum = room->openPrivateSlotNum();
|
||||||
room_info->curMemberNum = room->curMemberNum();
|
room_info->curMemberNum = room->curMemberNum();
|
||||||
room_info->passwordSlotMask = room->curMemberNum();
|
room_info->passwordSlotMask = room->passwordSlotMask();
|
||||||
|
|
||||||
if (auto owner = room->owner())
|
if (auto owner = room->owner())
|
||||||
{
|
{
|
||||||
vm::ptr<SceNpUserInfo2> owner_info(allocate(sizeof(SceNpUserInfo2)));
|
vm::ptr<SceNpUserInfo2> owner_info(allocate(sizeof(SceNpUserInfo2)));
|
||||||
@ -138,6 +115,35 @@ void np_handler::SearchRoomReponse_to_SceNpMatching2SearchRoomResponse(const Sea
|
|||||||
room_info->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();
|
||||||
|
search_resp->range.total = resp->total();
|
||||||
|
|
||||||
|
if (resp->rooms() && resp->rooms()->size() != 0)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
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
|
||||||
|
{
|
||||||
|
search_resp->roomDataExternal = room_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
previous_next = vm::cast(room_info.addr());
|
||||||
|
|
||||||
|
RoomDataExternal_to_SceNpMatching2RoomDataExternal(room, room_info.get_ptr());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
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 np_handler::RoomDataInternal_to_SceNpMatching2RoomDataInternal(const RoomDataInternal* resp, SceNpMatching2RoomDataInternal* room_info, const SceNpId& npid)
|
||||||
{
|
{
|
||||||
u16 member_id = 0;
|
u16 member_id = 0;
|
||||||
|
@ -167,6 +167,15 @@ table LeaveRoomRequest {
|
|||||||
optData:PresenceOptionData;
|
optData:PresenceOptionData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
table GetRoomDataExternalListRequest {
|
||||||
|
roomIds:[uint64];
|
||||||
|
attrIds:[uint16];
|
||||||
|
}
|
||||||
|
|
||||||
|
table GetRoomDataExternalListResponse {
|
||||||
|
rooms:[RoomDataExternal];
|
||||||
|
}
|
||||||
|
|
||||||
table SetRoomDataExternalRequest {
|
table SetRoomDataExternalRequest {
|
||||||
roomId:uint64;
|
roomId:uint64;
|
||||||
roomSearchableIntAttrExternal:[IntAttr];
|
roomSearchableIntAttrExternal:[IntAttr];
|
||||||
@ -223,3 +232,19 @@ table RoomMessageInfo {
|
|||||||
srcMember:UserInfo2;
|
srcMember:UserInfo2;
|
||||||
msg:[uint8];
|
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,10 +44,11 @@ np_handler::np_handler()
|
|||||||
{
|
{
|
||||||
g_fxo->need<named_thread<signaling_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_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 (get_net_status() == CELL_NET_CTL_STATE_IPObtained)
|
||||||
{
|
{
|
||||||
@ -305,6 +306,11 @@ void np_handler::string_to_avatar_url(const std::string& str, SceNpAvatarUrl* av
|
|||||||
strcpy_trunc(avatar_url->data, str);
|
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)
|
void np_handler::init_NP(u32 poolsize, vm::ptr<void> poolptr)
|
||||||
{
|
{
|
||||||
// Init memory pool
|
// 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(&online_name, 0, sizeof(online_name));
|
||||||
memset(&avatar_url, 0, sizeof(avatar_url));
|
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();
|
std::string s_npid = g_cfg_rpcn.get_npid();
|
||||||
ensure(!s_npid.empty()); // It should have been generated before this
|
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:
|
case np_psn_status::disabled:
|
||||||
break;
|
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_online_name("RPCS3's user", &online_name);
|
||||||
np_handler::string_to_avatar_url("https://rpcs3.net/cdn/netplay/DefaultAvatar.png", &avatar_url);
|
np_handler::string_to_avatar_url("https://rpcs3.net/cdn/netplay/DefaultAvatar.png", &avatar_url);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case np_psn_status::rpcn:
|
case np_psn_status::psn_rpcn:
|
||||||
{
|
{
|
||||||
if (!is_psn_active)
|
if (!is_psn_active)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Connect RPCN client
|
std::lock_guard lock(mutex_rpcn);
|
||||||
if (!rpcn.connect(g_cfg_rpcn.get_host()))
|
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!");
|
rpcn_log.error("Connection to RPCN Failed!");
|
||||||
is_psn_active = false;
|
is_psn_active = false;
|
||||||
return;
|
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!");
|
rpcn_log.error("RPCN login attempt failed!");
|
||||||
is_psn_active = false;
|
is_psn_active = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
np_handler::string_to_online_name(rpcn.get_online_name(), &online_name);
|
np_handler::string_to_online_name(rpcn->get_online_name(), &online_name);
|
||||||
np_handler::string_to_avatar_url(rpcn.get_avatar_url(), &avatar_url);
|
np_handler::string_to_avatar_url(rpcn->get_avatar_url(), &avatar_url);
|
||||||
public_ip_addr = rpcn.get_addr_sig();
|
public_ip_addr = rpcn->get_addr_sig();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -376,10 +386,11 @@ void np_handler::terminate_NP()
|
|||||||
mpool_avail = 0;
|
mpool_avail = 0;
|
||||||
mpool_allocs.clear();
|
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_log.notice("Disconnecting from RPCN!");
|
||||||
rpcn.disconnect();
|
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{};
|
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;
|
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!");
|
rpcn_log.error("Disconnecting from RPCN!");
|
||||||
is_psn_active = false;
|
is_psn_active = false;
|
||||||
@ -457,8 +468,7 @@ u32 np_handler::get_server_status(SceNpMatching2ContextId ctx_id, vm::cptr<SceNp
|
|||||||
serv_info->server.serverId = server_id;
|
serv_info->server.serverId = server_id;
|
||||||
serv_info->server.status = SCE_NP_MATCHING2_SERVER_STATUS_AVAILABLE;
|
serv_info->server.status = SCE_NP_MATCHING2_SERVER_STATUS_AVAILABLE;
|
||||||
|
|
||||||
const auto cb_info = std::move(pending_requests.at(req_id));
|
const auto cb_info = take_pending_request(req_id);
|
||||||
pending_requests.erase(req_id);
|
|
||||||
|
|
||||||
sysutil_register_cb([=](ppu_thread& cb_ppu) -> s32
|
sysutil_register_cb([=](ppu_thread& cb_ppu) -> s32
|
||||||
{
|
{
|
||||||
@ -474,8 +484,7 @@ u32 np_handler::create_server_context(SceNpMatching2ContextId ctx_id, vm::cptr<S
|
|||||||
u32 req_id = generate_callback_info(ctx_id, optParam);
|
u32 req_id = generate_callback_info(ctx_id, optParam);
|
||||||
u32 event_key = get_event_key();
|
u32 event_key = get_event_key();
|
||||||
|
|
||||||
const auto cb_info = std::move(pending_requests.at(req_id));
|
const auto cb_info = take_pending_request(req_id);
|
||||||
pending_requests.erase(req_id);
|
|
||||||
|
|
||||||
sysutil_register_cb([=](ppu_thread& cb_ppu) -> s32
|
sysutil_register_cb([=](ppu_thread& cb_ppu) -> s32
|
||||||
{
|
{
|
||||||
@ -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);
|
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!");
|
rpcn_log.error("Disconnecting from RPCN!");
|
||||||
is_psn_active = false;
|
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);
|
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!");
|
rpcn_log.error("Disconnecting from RPCN!");
|
||||||
is_psn_active = false;
|
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);
|
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!");
|
rpcn_log.error("Disconnecting from RPCN!");
|
||||||
is_psn_active = false;
|
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);
|
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!");
|
rpcn_log.error("Disconnecting from RPCN!");
|
||||||
is_psn_active = false;
|
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);
|
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!");
|
rpcn_log.error("Disconnecting from RPCN!");
|
||||||
is_psn_active = false;
|
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);
|
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!");
|
rpcn_log.error("Disconnecting from RPCN!");
|
||||||
is_psn_active = false;
|
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);
|
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!");
|
rpcn_log.error("Disconnecting from RPCN!");
|
||||||
is_psn_active = false;
|
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);
|
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!");
|
rpcn_log.error("Disconnecting from RPCN!");
|
||||||
is_psn_active = false;
|
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);
|
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!");
|
rpcn_log.error("Disconnecting from RPCN!");
|
||||||
is_psn_active = false;
|
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);
|
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!");
|
rpcn_log.error("Disconnecting from RPCN!");
|
||||||
is_psn_active = false;
|
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)
|
void np_handler::req_sign_infos(const std::string& npid, u32 conn_id)
|
||||||
{
|
{
|
||||||
u32 req_id = get_req_id(0x3333);
|
u32 req_id = get_req_id(0x3333);
|
||||||
|
{
|
||||||
|
std::lock_guard lock(mutex_pending_sign_infos_requests);
|
||||||
pending_sign_infos_requests[req_id] = conn_id;
|
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!");
|
rpcn_log.error("Disconnecting from RPCN!");
|
||||||
is_psn_active = false;
|
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);
|
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!");
|
rpcn_log.error("Disconnecting from RPCN!");
|
||||||
is_psn_active = false;
|
is_psn_active = false;
|
||||||
@ -649,7 +674,6 @@ void np_handler::req_ticket(u32 /*version*/, const SceNpId* /*npid*/, const char
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
u32 np_handler::get_match2_event(SceNpMatching2EventKey event_key, u8* dest, u32 size)
|
u32 np_handler::get_match2_event(SceNpMatching2EventKey event_key, u8* dest, u32 size)
|
||||||
{
|
{
|
||||||
std::lock_guard lock(mutex_req_results);
|
std::lock_guard lock(mutex_req_results);
|
||||||
@ -663,20 +687,80 @@ u32 np_handler::get_match2_event(SceNpMatching2EventKey event_key, u8* dest, u32
|
|||||||
return size_copied;
|
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()()
|
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;
|
return;
|
||||||
|
|
||||||
while (thread_ctrl::state() != thread_state::aborting && !Emu.IsStopped())
|
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)
|
||||||
{
|
{
|
||||||
thread_ctrl::wait_for(200'000);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto replies = rpcn.get_replies();
|
auto replies = rpcn->get_replies();
|
||||||
for (auto& reply : replies)
|
for (auto& reply : replies)
|
||||||
{
|
{
|
||||||
const u16 command = reply.second.first;
|
const u16 command = reply.second.first;
|
||||||
@ -685,45 +769,99 @@ void np_handler::operator()()
|
|||||||
|
|
||||||
switch (command)
|
switch (command)
|
||||||
{
|
{
|
||||||
case CommandType::GetWorldList: reply_get_world_list(req_id, data); break;
|
case rpcn::CommandType::GetWorldList: reply_get_world_list(req_id, data); break;
|
||||||
case CommandType::CreateRoom: reply_create_join_room(req_id, data); break;
|
case rpcn::CommandType::CreateRoom: reply_create_join_room(req_id, data); break;
|
||||||
case CommandType::JoinRoom: reply_join_room(req_id, data); break;
|
case rpcn::CommandType::JoinRoom: reply_join_room(req_id, data); break;
|
||||||
case CommandType::LeaveRoom: reply_leave_room(req_id, data); break;
|
case rpcn::CommandType::LeaveRoom: reply_leave_room(req_id, data); break;
|
||||||
case CommandType::SearchRoom: reply_search_room(req_id, data); break;
|
case rpcn::CommandType::SearchRoom: reply_search_room(req_id, data); break;
|
||||||
case CommandType::SetRoomDataExternal: reply_set_roomdata_external(req_id, data); break;
|
case rpcn::CommandType::GetRoomDataExternalList: reply_get_roomdata_external_list(req_id, data); break;
|
||||||
case CommandType::GetRoomDataInternal: reply_get_roomdata_internal(req_id, data); break;
|
case rpcn::CommandType::SetRoomDataExternal: reply_set_roomdata_external(req_id, data); break;
|
||||||
case CommandType::SetRoomDataInternal: reply_set_roomdata_internal(req_id, data); break;
|
case rpcn::CommandType::GetRoomDataInternal: reply_get_roomdata_internal(req_id, data); break;
|
||||||
case CommandType::PingRoomOwner: reply_get_ping_info(req_id, data); break;
|
case rpcn::CommandType::SetRoomDataInternal: reply_set_roomdata_internal(req_id, data); break;
|
||||||
case CommandType::SendRoomMessage: reply_send_room_message(req_id, data); break;
|
case rpcn::CommandType::PingRoomOwner: reply_get_ping_info(req_id, data); break;
|
||||||
case CommandType::RequestSignalingInfos: reply_req_sign_infos(req_id, data); break;
|
case rpcn::CommandType::SendRoomMessage: reply_send_room_message(req_id, data); break;
|
||||||
case CommandType::RequestTicket: reply_req_ticket(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;
|
default: rpcn_log.error("Unknown reply(%d) received!", command); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto notifications = rpcn.get_notifications();
|
auto notifications = rpcn->get_notifications();
|
||||||
for (auto& notif : notifications)
|
for (auto& notif : notifications)
|
||||||
{
|
{
|
||||||
switch (notif.first)
|
switch (notif.first)
|
||||||
{
|
{
|
||||||
case NotificationType::UserJoinedRoom: notif_user_joined_room(notif.second); break;
|
case rpcn::NotificationType::UserJoinedRoom: notif_user_joined_room(notif.second); break;
|
||||||
case NotificationType::UserLeftRoom: notif_user_left_room(notif.second); break;
|
case rpcn::NotificationType::UserLeftRoom: notif_user_left_room(notif.second); break;
|
||||||
case NotificationType::RoomDestroyed: notif_room_destroyed(notif.second); break;
|
case rpcn::NotificationType::RoomDestroyed: notif_room_destroyed(notif.second); break;
|
||||||
case NotificationType::SignalP2PConnect: notif_p2p_connect(notif.second); break;
|
case rpcn::NotificationType::SignalP2PConnect: notif_p2p_connect(notif.second); break;
|
||||||
case NotificationType::RoomMessageReceived: notif_room_message_received(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;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool np_handler::reply_get_world_list(u32 req_id, std::vector<u8>& reply_data)
|
bool np_handler::reply_get_world_list(u32 req_id, std::vector<u8>& reply_data)
|
||||||
{
|
{
|
||||||
if (pending_requests.count(req_id) == 0)
|
const auto cb_info = take_pending_request(req_id);
|
||||||
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);
|
|
||||||
|
|
||||||
vec_stream reply(reply_data, 1);
|
vec_stream reply(reply_data, 1);
|
||||||
|
|
||||||
@ -770,11 +908,7 @@ bool np_handler::reply_get_world_list(u32 req_id, std::vector<u8>& reply_data)
|
|||||||
|
|
||||||
bool np_handler::reply_create_join_room(u32 req_id, std::vector<u8>& reply_data)
|
bool np_handler::reply_create_join_room(u32 req_id, std::vector<u8>& reply_data)
|
||||||
{
|
{
|
||||||
if (pending_requests.count(req_id) == 0)
|
const auto cb_info = take_pending_request(req_id);
|
||||||
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);
|
|
||||||
|
|
||||||
vec_stream reply(reply_data, 1);
|
vec_stream reply(reply_data, 1);
|
||||||
auto create_room_resp = reply.get_rawdata();
|
auto create_room_resp = reply.get_rawdata();
|
||||||
@ -795,7 +929,7 @@ bool np_handler::reply_create_join_room(u32 req_id, std::vector<u8>& reply_data)
|
|||||||
// Establish Matching2 self signaling info
|
// Establish Matching2 self signaling info
|
||||||
auto& sigh = g_fxo->get<named_thread<signaling_handler>>();
|
auto& sigh = g_fxo->get<named_thread<signaling_handler>>();
|
||||||
sigh.set_self_sig2_info(room_info->roomId, 1);
|
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?
|
// TODO? Should this send a message to Signaling CB? Is this even necessary?
|
||||||
|
|
||||||
extra_nps::print_create_room_resp(room_resp);
|
extra_nps::print_create_room_resp(room_resp);
|
||||||
@ -811,11 +945,7 @@ bool np_handler::reply_create_join_room(u32 req_id, std::vector<u8>& reply_data)
|
|||||||
|
|
||||||
bool np_handler::reply_join_room(u32 req_id, std::vector<u8>& reply_data)
|
bool np_handler::reply_join_room(u32 req_id, std::vector<u8>& reply_data)
|
||||||
{
|
{
|
||||||
if (pending_requests.count(req_id) == 0)
|
const auto cb_info = take_pending_request(req_id);
|
||||||
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);
|
|
||||||
|
|
||||||
vec_stream reply(reply_data, 1);
|
vec_stream reply(reply_data, 1);
|
||||||
|
|
||||||
@ -839,7 +969,7 @@ bool np_handler::reply_join_room(u32 req_id, std::vector<u8>& reply_data)
|
|||||||
// Establish Matching2 self signaling info
|
// Establish Matching2 self signaling info
|
||||||
auto& sigh = g_fxo->get<named_thread<signaling_handler>>();
|
auto& sigh = g_fxo->get<named_thread<signaling_handler>>();
|
||||||
sigh.set_self_sig2_info(room_info->roomId, member_id);
|
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?
|
// TODO? Should this send a message to Signaling CB? Is this even necessary?
|
||||||
|
|
||||||
sysutil_register_cb([=](ppu_thread& cb_ppu) -> s32
|
sysutil_register_cb([=](ppu_thread& cb_ppu) -> s32
|
||||||
@ -853,11 +983,7 @@ bool np_handler::reply_join_room(u32 req_id, std::vector<u8>& reply_data)
|
|||||||
|
|
||||||
bool np_handler::reply_leave_room(u32 req_id, std::vector<u8>& reply_data)
|
bool np_handler::reply_leave_room(u32 req_id, std::vector<u8>& reply_data)
|
||||||
{
|
{
|
||||||
if (pending_requests.count(req_id) == 0)
|
const auto cb_info = take_pending_request(req_id);
|
||||||
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);
|
|
||||||
|
|
||||||
vec_stream reply(reply_data, 1);
|
vec_stream reply(reply_data, 1);
|
||||||
u64 room_id = reply.get<u64>();
|
u64 room_id = reply.get<u64>();
|
||||||
@ -881,11 +1007,7 @@ bool np_handler::reply_leave_room(u32 req_id, std::vector<u8>& reply_data)
|
|||||||
|
|
||||||
bool np_handler::reply_search_room(u32 req_id, std::vector<u8>& reply_data)
|
bool np_handler::reply_search_room(u32 req_id, std::vector<u8>& reply_data)
|
||||||
{
|
{
|
||||||
if (pending_requests.count(req_id) == 0)
|
const auto cb_info = take_pending_request(req_id);
|
||||||
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);
|
|
||||||
|
|
||||||
vec_stream reply(reply_data, 1);
|
vec_stream reply(reply_data, 1);
|
||||||
auto search_room_resp = reply.get_rawdata();
|
auto search_room_resp = reply.get_rawdata();
|
||||||
@ -897,7 +1019,32 @@ bool np_handler::reply_search_room(u32 req_id, std::vector<u8>& reply_data)
|
|||||||
auto resp = flatbuffers::GetRoot<SearchRoomResponse>(search_room_resp.data());
|
auto resp = flatbuffers::GetRoot<SearchRoomResponse>(search_room_resp.data());
|
||||||
SceNpMatching2SearchRoomResponse* search_resp = reinterpret_cast<SceNpMatching2SearchRoomResponse*>(allocate_req_result(event_key, sizeof(SceNpMatching2SearchRoomResponse)));
|
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;
|
||||||
|
});
|
||||||
|
|
||||||
|
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
|
sysutil_register_cb([=](ppu_thread& cb_ppu) -> s32
|
||||||
{
|
{
|
||||||
@ -910,11 +1057,7 @@ bool np_handler::reply_search_room(u32 req_id, std::vector<u8>& reply_data)
|
|||||||
|
|
||||||
bool np_handler::reply_set_roomdata_external(u32 req_id, std::vector<u8>& /*reply_data*/)
|
bool np_handler::reply_set_roomdata_external(u32 req_id, std::vector<u8>& /*reply_data*/)
|
||||||
{
|
{
|
||||||
if (pending_requests.count(req_id) == 0)
|
const auto cb_info = take_pending_request(req_id);
|
||||||
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);
|
|
||||||
|
|
||||||
u32 event_key = get_event_key(); // Unsure if necessary if there is no data
|
u32 event_key = get_event_key(); // Unsure if necessary if there is no data
|
||||||
|
|
||||||
@ -929,11 +1072,7 @@ bool np_handler::reply_set_roomdata_external(u32 req_id, std::vector<u8>& /*repl
|
|||||||
|
|
||||||
bool np_handler::reply_get_roomdata_internal(u32 req_id, std::vector<u8>& reply_data)
|
bool np_handler::reply_get_roomdata_internal(u32 req_id, std::vector<u8>& reply_data)
|
||||||
{
|
{
|
||||||
if (pending_requests.count(req_id) == 0)
|
const auto cb_info = take_pending_request(req_id);
|
||||||
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);
|
|
||||||
|
|
||||||
vec_stream reply(reply_data, 1);
|
vec_stream reply(reply_data, 1);
|
||||||
|
|
||||||
@ -963,11 +1102,7 @@ bool np_handler::reply_get_roomdata_internal(u32 req_id, std::vector<u8>& reply_
|
|||||||
|
|
||||||
bool np_handler::reply_set_roomdata_internal(u32 req_id, std::vector<u8>& /*reply_data*/)
|
bool np_handler::reply_set_roomdata_internal(u32 req_id, std::vector<u8>& /*reply_data*/)
|
||||||
{
|
{
|
||||||
if (pending_requests.count(req_id) == 0)
|
const auto cb_info = take_pending_request(req_id);
|
||||||
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);
|
|
||||||
|
|
||||||
u32 event_key = get_event_key(); // Unsure if necessary if there is no data
|
u32 event_key = get_event_key(); // Unsure if necessary if there is no data
|
||||||
|
|
||||||
@ -982,11 +1117,7 @@ bool np_handler::reply_set_roomdata_internal(u32 req_id, std::vector<u8>& /*repl
|
|||||||
|
|
||||||
bool np_handler::reply_get_ping_info(u32 req_id, std::vector<u8>& reply_data)
|
bool np_handler::reply_get_ping_info(u32 req_id, std::vector<u8>& reply_data)
|
||||||
{
|
{
|
||||||
if (pending_requests.count(req_id) == 0)
|
const auto cb_info = take_pending_request(req_id);
|
||||||
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);
|
|
||||||
|
|
||||||
vec_stream reply(reply_data, 1);
|
vec_stream reply(reply_data, 1);
|
||||||
|
|
||||||
@ -1012,11 +1143,7 @@ bool np_handler::reply_get_ping_info(u32 req_id, std::vector<u8>& reply_data)
|
|||||||
|
|
||||||
bool np_handler::reply_send_room_message(u32 req_id, std::vector<u8>& /*reply_data*/)
|
bool np_handler::reply_send_room_message(u32 req_id, std::vector<u8>& /*reply_data*/)
|
||||||
{
|
{
|
||||||
if (pending_requests.count(req_id) == 0)
|
const auto cb_info = take_pending_request(req_id);
|
||||||
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);
|
|
||||||
|
|
||||||
sysutil_register_cb([=](ppu_thread& cb_ppu) -> s32
|
sysutil_register_cb([=](ppu_thread& cb_ppu) -> s32
|
||||||
{
|
{
|
||||||
@ -1029,11 +1156,12 @@ bool np_handler::reply_send_room_message(u32 req_id, std::vector<u8>& /*reply_da
|
|||||||
|
|
||||||
bool np_handler::reply_req_sign_infos(u32 req_id, std::vector<u8>& reply_data)
|
bool np_handler::reply_req_sign_infos(u32 req_id, std::vector<u8>& reply_data)
|
||||||
{
|
{
|
||||||
if (!pending_sign_infos_requests.count(req_id))
|
u32 conn_id;
|
||||||
return error_and_disconnect("Unexpected reply ID to req RequestSignalingInfos");
|
{
|
||||||
|
std::lock_guard lock(mutex_pending_sign_infos_requests);
|
||||||
u32 conn_id = pending_sign_infos_requests.at(req_id);
|
conn_id = pending_sign_infos_requests.at(req_id);
|
||||||
pending_sign_infos_requests.erase(req_id);
|
pending_sign_infos_requests.erase(req_id);
|
||||||
|
}
|
||||||
|
|
||||||
vec_stream reply(reply_data, 1);
|
vec_stream reply(reply_data, 1);
|
||||||
u32 addr = reply.get<u32>();
|
u32 addr = reply.get<u32>();
|
||||||
@ -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)
|
bool np_handler::error_and_disconnect(const std::string& error_msg)
|
||||||
{
|
{
|
||||||
rpcn_log.error("%s", error_msg);
|
rpcn_log.error("%s", error_msg);
|
||||||
rpcn.disconnect();
|
rpcn.reset();
|
||||||
|
|
||||||
return false;
|
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);
|
nph_log.warning("Callback used is 0x%x", ret.cb);
|
||||||
|
|
||||||
|
{
|
||||||
|
std::lock_guard lock(mutex_pending_requests);
|
||||||
pending_requests[req_id] = std::move(ret);
|
pending_requests[req_id] = std::move(ret);
|
||||||
|
}
|
||||||
|
|
||||||
return req_id;
|
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)
|
u8* np_handler::allocate_req_result(u32 event_key, usz size)
|
||||||
{
|
{
|
||||||
std::lock_guard lock(mutex_req_results);
|
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;
|
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 ip_to_string(u32 addr);
|
||||||
static std::string ether_to_string(std::array<u8, 6>& ether);
|
static std::string ether_to_string(std::array<u8, 6>& ether);
|
||||||
// Helpers for setting various structures from string
|
// Helpers for setting various structures from string
|
||||||
static void string_to_npid(const std::string&, SceNpId* npid);
|
static void string_to_npid(const std::string& str, SceNpId* npid);
|
||||||
static void string_to_online_name(const std::string&, SceNpOnlineName* online_name);
|
static void string_to_online_name(const std::string& str, SceNpOnlineName* online_name);
|
||||||
static void string_to_avatar_url(const std::string&, SceNpAvatarUrl* avatar_url);
|
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
|
// DNS hooking functions
|
||||||
void add_dns_spy(u32 sock);
|
void add_dns_spy(u32 sock);
|
||||||
@ -47,16 +48,6 @@ public:
|
|||||||
std::vector<u8> get_dns_packet(u32 sock);
|
std::vector<u8> get_dns_packet(u32 sock);
|
||||||
s32 analyze_dns_packet(s32 s, const u8* buf, u32 len);
|
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)
|
// handles async messages from server(only needed for RPCN)
|
||||||
void operator()();
|
void operator()();
|
||||||
|
|
||||||
@ -76,9 +67,25 @@ public:
|
|||||||
vm::ptr<SceNpManagerCallback> manager_cb{}; // Connection status and tickets
|
vm::ptr<SceNpManagerCallback> manager_cb{}; // Connection status and tickets
|
||||||
vm::ptr<void> manager_cb_arg{};
|
vm::ptr<void> manager_cb_arg{};
|
||||||
|
|
||||||
// Registered by SceNpCommunicationId
|
// Basic event handler;
|
||||||
vm::ptr<SceNpBasicEventHandler> basic_handler;
|
struct
|
||||||
vm::ptr<void> basic_handler_arg;
|
{
|
||||||
|
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
|
// Those should probably be under match2 ctx
|
||||||
vm::ptr<SceNpMatching2RoomEventCallback> room_event_cb{}; // Room events
|
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 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 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 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 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 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);
|
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);
|
u32 get_match2_event(SceNpMatching2EventKey event_key, u8* dest, u32 size);
|
||||||
|
|
||||||
|
// Friend stuff
|
||||||
|
u32 get_num_friends();
|
||||||
|
u32 get_num_blocks();
|
||||||
|
|
||||||
// Misc stuff
|
// 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);
|
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; }
|
const std::vector<u8>& get_ticket() const
|
||||||
|
{
|
||||||
|
return current_ticket;
|
||||||
|
}
|
||||||
u32 add_players_to_history(vm::cptr<SceNpId> npids, u32 count);
|
u32 add_players_to_history(vm::cptr<SceNpId> npids, u32 count);
|
||||||
|
|
||||||
// For signaling
|
// For signaling
|
||||||
@ -119,7 +134,7 @@ public:
|
|||||||
|
|
||||||
static constexpr std::string_view thread_name = "NP Handler Thread";
|
static constexpr std::string_view thread_name = "NP Handler Thread";
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
// Various generic helpers
|
// Various generic helpers
|
||||||
bool discover_ip_address();
|
bool discover_ip_address();
|
||||||
bool discover_ether_address();
|
bool discover_ether_address();
|
||||||
@ -138,6 +153,7 @@ protected:
|
|||||||
bool reply_join_room(u32 req_id, std::vector<u8>& reply_data);
|
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_leave_room(u32 req_id, std::vector<u8>& reply_data);
|
||||||
bool reply_search_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_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_get_roomdata_internal(u32 req_id, std::vector<u8>& reply_data);
|
||||||
bool reply_set_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 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 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 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);
|
u16 RoomDataInternal_to_SceNpMatching2RoomDataInternal(const RoomDataInternal* resp, SceNpMatching2RoomDataInternal* room_resp, const SceNpId& npid);
|
||||||
void RoomMemberUpdateInfo_to_SceNpMatching2RoomMemberUpdateInfo(const RoomMemberUpdateInfo* resp, SceNpMatching2RoomMemberUpdateInfo* room_info);
|
void RoomMemberUpdateInfo_to_SceNpMatching2RoomMemberUpdateInfo(const RoomMemberUpdateInfo* resp, SceNpMatching2RoomMemberUpdateInfo* room_info);
|
||||||
void RoomUpdateInfo_to_SceNpMatching2RoomUpdateInfo(const RoomUpdateInfo* update_info, SceNpMatching2RoomUpdateInfo* sce_update_info);
|
void RoomUpdateInfo_to_SceNpMatching2RoomUpdateInfo(const RoomUpdateInfo* update_info, SceNpMatching2RoomUpdateInfo* sce_update_info);
|
||||||
@ -164,11 +182,17 @@ protected:
|
|||||||
vm::ptr<void> cb_arg;
|
vm::ptr<void> cb_arg;
|
||||||
};
|
};
|
||||||
u32 generate_callback_info(SceNpMatching2ContextId ctx_id, vm::cptr<SceNpMatching2RequestOptParam> optParam);
|
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;
|
std::unordered_map<u32, callback_info> pending_requests;
|
||||||
|
shared_mutex mutex_pending_sign_infos_requests;
|
||||||
std::unordered_map<u32, u32> 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_connected = false;
|
||||||
bool is_psn_active = false;
|
bool is_psn_active = false;
|
||||||
|
|
||||||
@ -213,5 +237,6 @@ protected:
|
|||||||
u8* allocate_req_result(u32 event_key, usz size);
|
u8* allocate_req_result(u32 event_key, usz size);
|
||||||
|
|
||||||
// RPCN
|
// 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 <unordered_map>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <thread>
|
||||||
|
#include <semaphore>
|
||||||
#include "Utilities/mutex.h"
|
#include "Utilities/mutex.h"
|
||||||
|
|
||||||
#include "util/asm.hpp"
|
#include "util/asm.hpp"
|
||||||
@ -26,8 +28,7 @@ class vec_stream
|
|||||||
public:
|
public:
|
||||||
vec_stream() = delete;
|
vec_stream() = delete;
|
||||||
vec_stream(std::vector<u8>& _vec, usz initial_index = 0)
|
vec_stream(std::vector<u8>& _vec, usz initial_index = 0)
|
||||||
: vec(_vec)
|
: vec(_vec), i(initial_index) {}
|
||||||
, i(initial_index){}
|
|
||||||
bool is_error() const
|
bool is_error() const
|
||||||
{
|
{
|
||||||
return error;
|
return error;
|
||||||
@ -101,18 +102,25 @@ protected:
|
|||||||
bool error = false;
|
bool error = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace rpcn
|
||||||
|
{
|
||||||
enum CommandType : u16
|
enum CommandType : u16
|
||||||
{
|
{
|
||||||
Login,
|
Login,
|
||||||
Terminate,
|
Terminate,
|
||||||
Create,
|
Create,
|
||||||
SendToken,
|
SendToken,
|
||||||
|
AddFriend,
|
||||||
|
RemoveFriend,
|
||||||
|
AddBlock,
|
||||||
|
RemoveBlock,
|
||||||
GetServerList,
|
GetServerList,
|
||||||
GetWorldList,
|
GetWorldList,
|
||||||
CreateRoom,
|
CreateRoom,
|
||||||
JoinRoom,
|
JoinRoom,
|
||||||
LeaveRoom,
|
LeaveRoom,
|
||||||
SearchRoom,
|
SearchRoom,
|
||||||
|
GetRoomDataExternalList,
|
||||||
SetRoomDataExternal,
|
SetRoomDataExternal,
|
||||||
GetRoomDataInternal,
|
GetRoomDataInternal,
|
||||||
SetRoomDataInternal,
|
SetRoomDataInternal,
|
||||||
@ -120,10 +128,40 @@ enum CommandType : u16
|
|||||||
SendRoomMessage,
|
SendRoomMessage,
|
||||||
RequestSignalingInfos,
|
RequestSignalingInfos,
|
||||||
RequestTicket,
|
RequestTicket,
|
||||||
|
SendMessage,
|
||||||
};
|
};
|
||||||
|
|
||||||
class rpcn_client
|
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,
|
||||||
|
};
|
||||||
|
|
||||||
enum PacketType : u8
|
enum PacketType : u8
|
||||||
{
|
{
|
||||||
Request,
|
Request,
|
||||||
@ -134,32 +172,147 @@ class rpcn_client
|
|||||||
|
|
||||||
enum ErrorType : u8
|
enum ErrorType : u8
|
||||||
{
|
{
|
||||||
NoError,
|
NoError, // No error
|
||||||
Malformed,
|
Malformed, // Query was malformed, critical error that should close the connection
|
||||||
Invalid,
|
Invalid, // The request type is invalid(wrong stage?)
|
||||||
InvalidInput,
|
InvalidInput, // The Input doesn't fit the constraints of the request
|
||||||
ErrorLogin,
|
TooSoon, // Time limited operation attempted too soon
|
||||||
ErrorCreate,
|
LoginError, // An error happened related to login
|
||||||
AlreadyLoggedIn,
|
LoginAlreadyLoggedIn, // Can't log in because you're already logged in
|
||||||
AlreadyJoined,
|
LoginInvalidUsername, // Invalid username
|
||||||
DbFail,
|
LoginInvalidPassword, // Invalid password
|
||||||
NotFound,
|
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,
|
Unsupported,
|
||||||
__error_last
|
__error_last
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
using friend_cb_func = void (*)(void* param, NotificationType ntype, const std::string& username, bool status);
|
||||||
rpcn_client(bool in_config = false);
|
using message_cb_func = void (*)(void* param, const std::shared_ptr<std::pair<std::string, message_data>> new_msg, u64 msg_id);
|
||||||
~rpcn_client();
|
|
||||||
|
|
||||||
|
struct friend_data
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
class rpcn_client
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
static inline std::weak_ptr<rpcn_client> instance;
|
||||||
|
static inline shared_mutex inst_mutex;
|
||||||
|
|
||||||
|
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::binary_semaphore sem_reader, sem_writer, sem_rpcn;
|
||||||
|
std::mutex mutex_read, mutex_write;
|
||||||
|
|
||||||
|
std::thread thread_rpcn, thread_rpcn_reader, thread_rpcn_writer;
|
||||||
|
|
||||||
|
atomic_t<bool> terminate = false;
|
||||||
|
|
||||||
|
atomic_t<u32> num_failures = 0;
|
||||||
|
atomic_t<rpcn_state> state = rpcn_state::failure_no_failure;
|
||||||
|
|
||||||
|
std::vector<std::vector<u8>> packets_to_send;
|
||||||
|
std::mutex mutex_packets_to_send;
|
||||||
|
|
||||||
|
// Friends related
|
||||||
|
shared_mutex mutex_friends;
|
||||||
|
std::set<std::pair<friend_cb_func, void*>> friend_cbs;
|
||||||
|
friend_data friend_infos;
|
||||||
|
|
||||||
|
void handle_friend_notification(u16 command, std::vector<u8> data);
|
||||||
|
|
||||||
|
void handle_message(std::vector<u8> data);
|
||||||
|
|
||||||
|
private:
|
||||||
|
rpcn_client();
|
||||||
|
|
||||||
|
void rpcn_reader_thread();
|
||||||
|
void rpcn_writer_thread();
|
||||||
|
void rpcn_thread();
|
||||||
|
|
||||||
|
bool handle_input();
|
||||||
|
bool handle_output();
|
||||||
|
|
||||||
|
void add_packet(const std::vector<u8> packet);
|
||||||
|
|
||||||
|
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 connect(const std::string& host);
|
||||||
bool login(const std::string& npid, const std::string& password, const std::string& token);
|
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();
|
void disconnect();
|
||||||
bool manage_connection();
|
|
||||||
|
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::vector<std::pair<u16, std::vector<u8>>> get_notifications();
|
||||||
std::unordered_map<u32, std::pair<u16, std::vector<u8>>> get_replies();
|
std::unordered_map<u32, std::pair<u16, std::vector<u8>>> get_replies();
|
||||||
void abort();
|
|
||||||
|
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
|
// Synchronous requests
|
||||||
bool get_server_list(u32 req_id, const SceNpCommunicationId& communication_id, std::vector<u16>& server_list);
|
bool get_server_list(u32 req_id, const SceNpCommunicationId& communication_id, std::vector<u16>& server_list);
|
||||||
@ -169,6 +322,7 @@ public:
|
|||||||
bool join_room(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2JoinRoomRequest* 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 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 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 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 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 set_roomdata_internal(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2SetRoomDataInternalRequest* req);
|
||||||
@ -176,6 +330,7 @@ public:
|
|||||||
bool send_room_message(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2SendRoomMessageRequest* req);
|
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_sign_infos(u32 req_id, const std::string& npid);
|
||||||
bool req_ticket(u32 req_id, const std::string& service_id);
|
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
|
const std::string& get_online_name() const
|
||||||
{
|
{
|
||||||
@ -195,40 +350,22 @@ public:
|
|||||||
return port_sig.load();
|
return port_sig.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
enum class recvn_result
|
bool get_reply(u64 expected_id, std::vector<u8>& data);
|
||||||
{
|
|
||||||
recvn_success,
|
|
||||||
recvn_nodata,
|
|
||||||
recvn_timeout,
|
|
||||||
recvn_noconn,
|
|
||||||
recvn_fatal,
|
|
||||||
};
|
|
||||||
|
|
||||||
recvn_result recvn(u8* buf, usz n);
|
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 get_reply(u32 expected_id, std::vector<u8>& data);
|
bool forge_send_reply(u16 command, u64 packet_id, const std::vector<u8>& data, std::vector<u8>& reply_data);
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
bool is_error(ErrorType err) const;
|
bool is_error(ErrorType err) const;
|
||||||
bool error_and_disconnect(const std::string& error_mgs);
|
bool error_and_disconnect(const std::string& error_mgs);
|
||||||
bool is_abort() const;
|
|
||||||
|
|
||||||
std::string get_wolfssl_error(int error) const;
|
std::string get_wolfssl_error(WOLFSSL* wssl, int error) const;
|
||||||
|
|
||||||
protected:
|
|
||||||
atomic_t<bool> connected = false;
|
|
||||||
atomic_t<bool> authentified = false;
|
|
||||||
|
|
||||||
|
private:
|
||||||
WOLFSSL_CTX* wssl_ctx = nullptr;
|
WOLFSSL_CTX* wssl_ctx = nullptr;
|
||||||
WOLFSSL* wssl = nullptr;
|
WOLFSSL* read_wssl = nullptr;
|
||||||
|
WOLFSSL* write_wssl = nullptr;
|
||||||
bool in_config = false;
|
|
||||||
bool abort_config = false;
|
|
||||||
|
|
||||||
atomic_t<bool> server_info_received = false;
|
atomic_t<bool> server_info_received = false;
|
||||||
u32 received_version = 0;
|
u32 received_version = 0;
|
||||||
@ -239,12 +376,33 @@ protected:
|
|||||||
sockaddr_in addr_rpcn{};
|
sockaddr_in addr_rpcn{};
|
||||||
sockaddr_in addr_rpcn_udp{};
|
sockaddr_in addr_rpcn_udp{};
|
||||||
int sockfd = 0;
|
int sockfd = 0;
|
||||||
shared_mutex mutex_socket;
|
|
||||||
|
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;
|
shared_mutex mutex_notifs, mutex_replies, mutex_replies_sync;
|
||||||
std::vector<std::pair<u16, std::vector<u8>>> notifications; // notif type / data
|
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; // req id / (command / data)
|
||||||
std::unordered_map<u32, std::pair<u16, std::vector<u8>>> replies_sync; // same but for sync replies(Login, Create, GetServerList)
|
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 online_name{};
|
||||||
std::string avatar_url{};
|
std::string avatar_url{};
|
||||||
@ -254,3 +412,5 @@ protected:
|
|||||||
atomic_t<u32> addr_sig{};
|
atomic_t<u32> addr_sig{};
|
||||||
atomic_t<u16> port_sig{};
|
atomic_t<u16> port_sig{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace rpcn
|
||||||
|
@ -290,6 +290,7 @@ void signaling_handler::process_incoming_messages()
|
|||||||
retire_packet(si, signal_connect);
|
retire_packet(si, signal_connect);
|
||||||
// connection is active
|
// connection is active
|
||||||
update_si_addr(si, op_addr, op_port);
|
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);
|
update_si_status(si, SCE_NP_SIGNALING_CONN_STATUS_ACTIVE);
|
||||||
break;
|
break;
|
||||||
case signal_confirm:
|
case signal_confirm:
|
||||||
@ -299,6 +300,7 @@ void signaling_handler::process_incoming_messages()
|
|||||||
retire_packet(si, signal_connect_ack);
|
retire_packet(si, signal_connect_ack);
|
||||||
// connection is active
|
// connection is active
|
||||||
update_si_addr(si, op_addr, op_port);
|
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);
|
update_si_status(si, SCE_NP_SIGNALING_CONN_STATUS_ACTIVE, true);
|
||||||
break;
|
break;
|
||||||
case signal_finished:
|
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)
|
void signaling_handler::update_si_status(std::shared_ptr<signaling_info>& si, s32 new_status, bool confirm_packet)
|
||||||
{
|
{
|
||||||
if (!si)
|
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);
|
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)
|
if (send_packet_from_p2p_port(packet, dest) == -1)
|
||||||
{
|
{
|
||||||
sign_log.error("Failed to send signaling packet to %s:%d", ip_str, port);
|
sign_log.error("Failed to send signaling packet to %s:%d", ip_str, port);
|
||||||
|
@ -21,6 +21,10 @@ struct signaling_info
|
|||||||
u32 addr = 0;
|
u32 addr = 0;
|
||||||
u16 port = 0;
|
u16 port = 0;
|
||||||
|
|
||||||
|
// User seen from that peer
|
||||||
|
u32 mapped_addr = 0;
|
||||||
|
u16 mapped_port = 0;
|
||||||
|
|
||||||
// For handler
|
// For handler
|
||||||
steady_clock::time_point time_last_msg_recvd = steady_clock::now();
|
steady_clock::time_point time_last_msg_recvd = steady_clock::now();
|
||||||
|
|
||||||
@ -84,6 +88,8 @@ private:
|
|||||||
be_t<u32> signature = SIGNALING_SIGNATURE;
|
be_t<u32> signature = SIGNALING_SIGNATURE;
|
||||||
le_t<u32> version;
|
le_t<u32> version;
|
||||||
le_t<SignalingCommand> command;
|
le_t<SignalingCommand> command;
|
||||||
|
le_t<u32> sent_addr;
|
||||||
|
le_t<u16> sent_port;
|
||||||
union {
|
union {
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
@ -117,6 +123,7 @@ private:
|
|||||||
|
|
||||||
u32 create_sig_infos(const SceNpId* npid);
|
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_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 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_sig_callback(u32 conn_id, int event);
|
||||||
void signal_ext_sig_callback(u32 conn_id, int event) const;
|
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 MsgDialogBase>()> get_msg_dialog;
|
||||||
std::function<std::shared_ptr<class OskDialogBase>()> get_osk_dialog;
|
std::function<std::shared_ptr<class OskDialogBase>()> get_osk_dialog;
|
||||||
std::function<std::unique_ptr<class SaveDialogBase>()> get_save_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::unique_ptr<class TrophyNotificationBase>()> get_trophy_notification_dialog;
|
||||||
std::function<std::string(localized_string_id, const char*)> get_localized_string;
|
std::function<std::string(localized_string_id, const char*)> get_localized_string;
|
||||||
std::function<std::u32string(localized_string_id, const char*)> get_localized_u32string;
|
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)
|
switch (value)
|
||||||
{
|
{
|
||||||
case np_psn_status::disabled: return "Disconnected";
|
case np_psn_status::disabled: return "Disconnected";
|
||||||
case np_psn_status::fake: return "Simulated";
|
case np_psn_status::psn_fake: return "Simulated";
|
||||||
case np_psn_status::rpcn: return "RPCN";
|
case np_psn_status::psn_rpcn: return "RPCN";
|
||||||
}
|
}
|
||||||
|
|
||||||
return unknown;
|
return unknown;
|
||||||
|
@ -184,8 +184,8 @@ enum class np_internet_status
|
|||||||
enum np_psn_status
|
enum np_psn_status
|
||||||
{
|
{
|
||||||
disabled,
|
disabled,
|
||||||
fake,
|
psn_fake,
|
||||||
rpcn,
|
psn_rpcn,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class shader_mode
|
enum class shader_mode
|
||||||
|
@ -303,6 +303,9 @@
|
|||||||
<ClCompile Include="QTGeneratedFiles\Debug\moc_pkg_install_dialog.cpp">
|
<ClCompile Include="QTGeneratedFiles\Debug\moc_pkg_install_dialog.cpp">
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||||
</ClCompile>
|
</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">
|
<ClCompile Include="QTGeneratedFiles\Debug\moc_register_editor_dialog.cpp">
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -330,6 +333,9 @@
|
|||||||
<ClCompile Include="QTGeneratedFiles\Debug\moc_screenshot_preview.cpp">
|
<ClCompile Include="QTGeneratedFiles\Debug\moc_screenshot_preview.cpp">
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||||
</ClCompile>
|
</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">
|
<ClCompile Include="QTGeneratedFiles\Debug\moc_settings.cpp">
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -495,6 +501,9 @@
|
|||||||
<ClCompile Include="QTGeneratedFiles\Release\moc_pkg_install_dialog.cpp">
|
<ClCompile Include="QTGeneratedFiles\Release\moc_pkg_install_dialog.cpp">
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||||
</ClCompile>
|
</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">
|
<ClCompile Include="QTGeneratedFiles\Release\moc_register_editor_dialog.cpp">
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -522,6 +531,9 @@
|
|||||||
<ClCompile Include="QTGeneratedFiles\Release\moc_screenshot_preview.cpp">
|
<ClCompile Include="QTGeneratedFiles\Release\moc_screenshot_preview.cpp">
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||||
</ClCompile>
|
</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">
|
<ClCompile Include="QTGeneratedFiles\Release\moc_settings.cpp">
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -582,10 +594,12 @@
|
|||||||
<ClCompile Include="rpcs3qt\patch_manager_dialog.cpp" />
|
<ClCompile Include="rpcs3qt\patch_manager_dialog.cpp" />
|
||||||
<ClCompile Include="rpcs3qt\pkg_install_dialog.cpp" />
|
<ClCompile Include="rpcs3qt\pkg_install_dialog.cpp" />
|
||||||
<ClCompile Include="rpcs3qt\persistent_settings.cpp" />
|
<ClCompile Include="rpcs3qt\persistent_settings.cpp" />
|
||||||
|
<ClCompile Include="rpcs3qt\recvmessage_dialog_frame.cpp" />
|
||||||
<ClCompile Include="rpcs3qt\render_creator.cpp" />
|
<ClCompile Include="rpcs3qt\render_creator.cpp" />
|
||||||
<ClCompile Include="rpcs3qt\rpcn_settings_dialog.cpp" />
|
<ClCompile Include="rpcs3qt\rpcn_settings_dialog.cpp" />
|
||||||
<ClCompile Include="rpcs3qt\screenshot_manager_dialog.cpp" />
|
<ClCompile Include="rpcs3qt\screenshot_manager_dialog.cpp" />
|
||||||
<ClCompile Include="rpcs3qt\screenshot_preview.cpp" />
|
<ClCompile Include="rpcs3qt\screenshot_preview.cpp" />
|
||||||
|
<ClCompile Include="rpcs3qt\sendmessage_dialog_frame.cpp" />
|
||||||
<ClCompile Include="rpcs3qt\settings.cpp" />
|
<ClCompile Include="rpcs3qt\settings.cpp" />
|
||||||
<ClCompile Include="rpcs3qt\skylander_dialog.cpp" />
|
<ClCompile Include="rpcs3qt\skylander_dialog.cpp" />
|
||||||
<ClCompile Include="rpcs3qt\tooltips.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)'=='Debug|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
||||||
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
||||||
</CustomBuild>
|
</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" />
|
<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" />
|
<ClInclude Include="rpcs3qt\stylesheets.h" />
|
||||||
<CustomBuild Include="rpcs3qt\skylander_dialog.h">
|
<CustomBuild Include="rpcs3qt\skylander_dialog.h">
|
||||||
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
||||||
|
@ -130,6 +130,9 @@
|
|||||||
<Filter Include="Gui\custom items">
|
<Filter Include="Gui\custom items">
|
||||||
<UniqueIdentifier>{949cff6d-9cc5-4a8a-a453-a5144da8ecf4}</UniqueIdentifier>
|
<UniqueIdentifier>{949cff6d-9cc5-4a8a-a453-a5144da8ecf4}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
<Filter Include="Gui\rpcn">
|
||||||
|
<UniqueIdentifier>{dfd401ec-dd22-4f8a-9dea-565a03efab6a}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="main.cpp">
|
<ClCompile Include="main.cpp">
|
||||||
@ -711,9 +714,6 @@
|
|||||||
<ClCompile Include="QTGeneratedFiles\Release\moc_downloader.cpp">
|
<ClCompile Include="QTGeneratedFiles\Release\moc_downloader.cpp">
|
||||||
<Filter>Generated Files\Release</Filter>
|
<Filter>Generated Files\Release</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="rpcs3qt\rpcn_settings_dialog.cpp">
|
|
||||||
<Filter>Gui\settings</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="QTGeneratedFiles\Debug\moc_rpcn_settings_dialog.cpp">
|
<ClCompile Include="QTGeneratedFiles\Debug\moc_rpcn_settings_dialog.cpp">
|
||||||
<Filter>Generated Files\Debug</Filter>
|
<Filter>Generated Files\Debug</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -756,6 +756,27 @@
|
|||||||
<ClCompile Include="QTGeneratedFiles\Release\moc_patch_creator_dialog.cpp">
|
<ClCompile Include="QTGeneratedFiles\Release\moc_patch_creator_dialog.cpp">
|
||||||
<Filter>Generated Files\Release</Filter>
|
<Filter>Generated Files\Release</Filter>
|
||||||
</ClCompile>
|
</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>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="Input\ds4_pad_handler.h">
|
<ClInclude Include="Input\ds4_pad_handler.h">
|
||||||
@ -1096,9 +1117,6 @@
|
|||||||
<CustomBuild Include="rpcs3qt\downloader.h">
|
<CustomBuild Include="rpcs3qt\downloader.h">
|
||||||
<Filter>Gui\network</Filter>
|
<Filter>Gui\network</Filter>
|
||||||
</CustomBuild>
|
</CustomBuild>
|
||||||
<CustomBuild Include="rpcs3qt\rpcn_settings_dialog.h">
|
|
||||||
<Filter>Gui\settings</Filter>
|
|
||||||
</CustomBuild>
|
|
||||||
<CustomBuild Include="rpcs3qt\localized_emu.h">
|
<CustomBuild Include="rpcs3qt\localized_emu.h">
|
||||||
<Filter>Gui\settings</Filter>
|
<Filter>Gui\settings</Filter>
|
||||||
</CustomBuild>
|
</CustomBuild>
|
||||||
@ -1111,6 +1129,15 @@
|
|||||||
<CustomBuild Include="rpcs3qt\patch_creator_dialog.h">
|
<CustomBuild Include="rpcs3qt\patch_creator_dialog.h">
|
||||||
<Filter>Gui\patch manager</Filter>
|
<Filter>Gui\patch manager</Filter>
|
||||||
</CustomBuild>
|
</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>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Image Include="rpcs3.ico" />
|
<Image Include="rpcs3.ico" />
|
||||||
|
@ -51,6 +51,7 @@ set(SRC_FILES
|
|||||||
progress_dialog.cpp
|
progress_dialog.cpp
|
||||||
qt_utils.cpp
|
qt_utils.cpp
|
||||||
register_editor_dialog.cpp
|
register_editor_dialog.cpp
|
||||||
|
recvmessage_dialog_frame.cpp
|
||||||
render_creator.cpp
|
render_creator.cpp
|
||||||
rpcn_settings_dialog.cpp
|
rpcn_settings_dialog.cpp
|
||||||
rsx_debugger.cpp
|
rsx_debugger.cpp
|
||||||
@ -60,6 +61,7 @@ set(SRC_FILES
|
|||||||
save_manager_dialog.cpp
|
save_manager_dialog.cpp
|
||||||
screenshot_manager_dialog.cpp
|
screenshot_manager_dialog.cpp
|
||||||
screenshot_preview.cpp
|
screenshot_preview.cpp
|
||||||
|
sendmessage_dialog_frame.cpp
|
||||||
settings.cpp
|
settings.cpp
|
||||||
settings_dialog.cpp
|
settings_dialog.cpp
|
||||||
skylander_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))
|
switch (static_cast<np_psn_status>(index))
|
||||||
{
|
{
|
||||||
case np_psn_status::disabled: return tr("Disconnected", "PSN Status");
|
case np_psn_status::disabled: return tr("Disconnected", "PSN Status");
|
||||||
case np_psn_status::fake: return tr("Simulated", "PSN Status");
|
case np_psn_status::psn_fake: return tr("Simulated", "PSN Status");
|
||||||
case np_psn_status::rpcn: return tr("RPCN", "PSN Status");
|
case np_psn_status::psn_rpcn: return tr("RPCN", "PSN Status");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case emu_settings_type::SleepTimersAccuracy:
|
case emu_settings_type::SleepTimersAccuracy:
|
||||||
|
@ -163,19 +163,3 @@ private Q_SLOTS:
|
|||||||
void handle_download_error(const QString& error);
|
void handle_download_error(const QString& error);
|
||||||
void handle_download_finished(const QByteArray& content);
|
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);
|
compat_item->setToolTip(game->compat.tooltip);
|
||||||
if (!game->compat.color.isEmpty())
|
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
|
// 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 "gui_application.h"
|
||||||
|
|
||||||
#include "qt_utils.h"
|
#include "qt_utils.h"
|
||||||
@ -23,6 +28,8 @@
|
|||||||
#include "save_data_dialog.h"
|
#include "save_data_dialog.h"
|
||||||
#include "msg_dialog_frame.h"
|
#include "msg_dialog_frame.h"
|
||||||
#include "osk_dialog_frame.h"
|
#include "osk_dialog_frame.h"
|
||||||
|
#include "recvmessage_dialog_frame.h"
|
||||||
|
#include "sendmessage_dialog_frame.h"
|
||||||
#include "stylesheets.h"
|
#include "stylesheets.h"
|
||||||
|
|
||||||
#include <QScreen>
|
#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_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_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_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.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); };
|
callbacks.on_run = [this](bool start_playtime) { OnEmulatorRun(start_playtime); };
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include <QTableWidget>
|
#include <QTableWidget>
|
||||||
#include <QHeaderView>
|
#include <QHeaderView>
|
||||||
#include <QTreeWidgetItem>
|
#include <QTreeWidgetItem>
|
||||||
|
#include <QPainter>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@ -17,6 +18,23 @@ namespace gui
|
|||||||
{
|
{
|
||||||
namespace utils
|
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>
|
template<typename T>
|
||||||
static QSet<T> list_to_set(const QList<T>& list)
|
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 <QPushButton>
|
||||||
#include <QRegExpValidator>
|
#include <QRegExpValidator>
|
||||||
#include <QInputDialog>
|
#include <QInputDialog>
|
||||||
|
#include <QGroupBox>
|
||||||
|
#include <QMenu>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
|
#include "qt_utils.h"
|
||||||
|
|
||||||
#include "rpcn_settings_dialog.h"
|
#include "rpcn_settings_dialog.h"
|
||||||
#include "Emu/NP/rpcn_config.h"
|
#include "Emu/NP/rpcn_config.h"
|
||||||
#include "Emu/NP/rpcn_client.h"
|
|
||||||
|
|
||||||
#include <wolfssl/ssl.h>
|
#include <wolfssl/ssl.h>
|
||||||
#include <wolfssl/openssl/evp.h>
|
#include <wolfssl/openssl/evp.h>
|
||||||
|
|
||||||
|
LOG_CHANNEL(rpcn_settings_log, "rpcn settings dlg");
|
||||||
|
|
||||||
|
const QString rpcn_state_to_qstr(rpcn::rpcn_state state)
|
||||||
|
{
|
||||||
|
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)
|
rpcn_settings_dialog::rpcn_settings_dialog(QWidget* parent)
|
||||||
: QDialog(parent)
|
: QDialog(parent)
|
||||||
{
|
{
|
||||||
setWindowTitle(tr("RPCN Configuration"));
|
setWindowTitle(tr("RPCN"));
|
||||||
setObjectName("rpcn_settings_dialog");
|
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));
|
setMinimumSize(QSize(400, 200));
|
||||||
|
|
||||||
QVBoxLayout* vbox_global = new QVBoxLayout();
|
QVBoxLayout* vbox_global = new QVBoxLayout();
|
||||||
@ -39,6 +109,10 @@ rpcn_settings_dialog::rpcn_settings_dialog(QWidget* parent)
|
|||||||
m_edit_token->setMaxLength(16);
|
m_edit_token->setMaxLength(16);
|
||||||
|
|
||||||
QPushButton* btn_create = new QPushButton(tr("Create Account"), 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);
|
QPushButton* btn_save = new QPushButton(tr("Save"), this);
|
||||||
|
|
||||||
vbox_labels->addWidget(label_host);
|
vbox_labels->addWidget(label_host);
|
||||||
@ -52,6 +126,8 @@ rpcn_settings_dialog::rpcn_settings_dialog(QWidget* parent)
|
|||||||
vbox_edits->addWidget(m_edit_token);
|
vbox_edits->addWidget(m_edit_token);
|
||||||
|
|
||||||
hbox_buttons->addWidget(btn_create);
|
hbox_buttons->addWidget(btn_create);
|
||||||
|
hbox_buttons->addWidget(btn_resendtoken);
|
||||||
|
hbox_buttons->addWidget(btn_changepass);
|
||||||
hbox_buttons->addStretch();
|
hbox_buttons->addStretch();
|
||||||
hbox_buttons->addWidget(btn_save);
|
hbox_buttons->addWidget(btn_save);
|
||||||
|
|
||||||
@ -63,28 +139,16 @@ rpcn_settings_dialog::rpcn_settings_dialog(QWidget* parent)
|
|||||||
|
|
||||||
setLayout(vbox_global);
|
setLayout(vbox_global);
|
||||||
|
|
||||||
connect(btn_chg_pass, &QAbstractButton::clicked, [this]()
|
connect(btn_chg_pass, &QAbstractButton::clicked, this, [this]()
|
||||||
{
|
{
|
||||||
QString password;
|
rpcn_ask_password_dialog ask_pass;
|
||||||
|
ask_pass.exec();
|
||||||
|
|
||||||
while (true)
|
auto password = ask_pass.get_password();
|
||||||
{
|
if (!password)
|
||||||
bool clicked_ok = false;
|
|
||||||
password = QInputDialog::getText(this, "Set/Change Password", "Set your password", QLineEdit::Password, "", &clicked_ok);
|
|
||||||
if (!clicked_ok)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (password.isEmpty())
|
const std::string pass_str = password.value();
|
||||||
{
|
|
||||||
QMessageBox::critical(this, tr("Wrong input"), tr("You need to enter a password!"), QMessageBox::Ok);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string pass_str = password.toStdString();
|
|
||||||
const std::string salt_str = "No matter where you go, everybody's connected.";
|
const std::string salt_str = "No matter where you go, everybody's connected.";
|
||||||
|
|
||||||
u8 salted_pass[SHA_DIGEST_SIZE];
|
u8 salted_pass[SHA_DIGEST_SIZE];
|
||||||
@ -101,14 +165,17 @@ rpcn_settings_dialog::rpcn_settings_dialog(QWidget* parent)
|
|||||||
|
|
||||||
g_cfg_rpcn.set_password(hash);
|
g_cfg_rpcn.set_password(hash);
|
||||||
g_cfg_rpcn.save();
|
g_cfg_rpcn.save();
|
||||||
|
|
||||||
|
QMessageBox::information(this, tr("RPCN Password Saved"), tr("Your password was saved successfully!"), QMessageBox::Ok);
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(btn_save, &QAbstractButton::clicked, [this]()
|
connect(btn_save, &QAbstractButton::clicked, this, [this]()
|
||||||
{
|
{
|
||||||
if (this->save_config())
|
if (this->save_config())
|
||||||
this->close();
|
this->close();
|
||||||
});
|
});
|
||||||
connect(btn_create, &QAbstractButton::clicked, [this]() { this->create_account(); });
|
connect(btn_create, &QAbstractButton::clicked, this, [this]()
|
||||||
|
{ this->create_account(); });
|
||||||
|
|
||||||
g_cfg_rpcn.load();
|
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()));
|
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 host = m_edit_host->text().toStdString();
|
||||||
const auto npid = m_edit_npid->text().toStdString();
|
const auto npid = m_edit_npid->text().toStdString();
|
||||||
const auto token = m_edit_token->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())
|
if (host.empty())
|
||||||
{
|
{
|
||||||
QMessageBox::critical(this, tr("Missing host"), tr("You need to enter a host for rpcn!"), QMessageBox::Ok);
|
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;
|
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);
|
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;
|
return false;
|
||||||
@ -164,7 +223,7 @@ bool rpcn_settings_dialog::save_config()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool rpcn_settings_dialog::create_account()
|
bool rpcn_account_dialog::create_account()
|
||||||
{
|
{
|
||||||
// Validate and save
|
// Validate and save
|
||||||
if (!save_config())
|
if (!save_config())
|
||||||
@ -176,7 +235,7 @@ bool rpcn_settings_dialog::create_account()
|
|||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
bool clicked_ok = false;
|
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)
|
if (!clicked_ok)
|
||||||
return false;
|
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 host = g_cfg_rpcn.get_host();
|
||||||
const auto npid = g_cfg_rpcn.get_npid();
|
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 avatar_url = "https://rpcs3.net/cdn/netplay/DefaultAvatar.png";
|
||||||
const auto password = g_cfg_rpcn.get_password();
|
const auto password = g_cfg_rpcn.get_password();
|
||||||
|
|
||||||
std::thread(
|
if (auto result = rpcn->wait_for_connection(); result != rpcn::rpcn_state::failure_no_failure)
|
||||||
[](const std::shared_ptr<rpcn_client> rpcn)
|
|
||||||
{
|
{
|
||||||
while (rpcn.use_count() != 1)
|
const QString error_message = tr("Failed to connect to RPCN server:\n%0").arg(rpcn_state_to_qstr(result));
|
||||||
rpcn->manage_connection();
|
QMessageBox::critical(this, tr("Error Connecting"), error_message, QMessageBox::Ok);
|
||||||
|
|
||||||
rpcn->disconnect();
|
|
||||||
},
|
|
||||||
rpcn)
|
|
||||||
.detach();
|
|
||||||
|
|
||||||
if (!rpcn->connect(host))
|
|
||||||
{
|
|
||||||
QMessageBox::critical(this, tr("Error Connecting"), tr("Failed to connect to RPCN server"), QMessageBox::Ok);
|
|
||||||
rpcn->abort();
|
|
||||||
return false;
|
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);
|
QString error_message;
|
||||||
rpcn->abort();
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QMessageBox::information(this, tr("Account created!"), tr("Your account has been created successfully!\nCheck your email for your token!"), QMessageBox::Ok);
|
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;
|
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
|
#pragma once
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
#include <QLineEdit>
|
#include <QLineEdit>
|
||||||
|
#include <QListWidget>
|
||||||
|
|
||||||
|
#include "Emu/NP/rpcn_client.h"
|
||||||
|
|
||||||
class rpcn_settings_dialog : public QDialog
|
class rpcn_settings_dialog : public QDialog
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
rpcn_settings_dialog(QWidget* parent = nullptr);
|
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 save_config();
|
||||||
bool create_account();
|
bool create_account();
|
||||||
@ -16,3 +27,51 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
QLineEdit *m_edit_host, *m_edit_npid, *m_edit_token;
|
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