Revert "Removed web service reminiscents" in preparation to fix multiplayer lobby list

This reverts commit ffc907460f.
This commit is contained in:
spectranator 2024-06-30 16:54:56 +02:00
parent cc81504195
commit 39af5e51ff
16 changed files with 196 additions and 2 deletions

3
.gitmodules vendored
View File

@ -28,6 +28,9 @@
[submodule "vcpkg"] [submodule "vcpkg"]
path = externals/vcpkg path = externals/vcpkg
url = https://github.com/microsoft/vcpkg.git url = https://github.com/microsoft/vcpkg.git
[submodule "cpp-jwt"]
path = externals/cpp-jwt
url = https://github.com/arun11299/cpp-jwt.git
[submodule "libadrenotools"] [submodule "libadrenotools"]
path = externals/libadrenotools path = externals/libadrenotools
url = https://github.com/bylaws/libadrenotools.git url = https://github.com/bylaws/libadrenotools.git

View File

@ -30,6 +30,8 @@ set(QT6_LOCATION "" CACHE PATH "Additional Location to search for Qt6 libraries
option(ENABLE_QT_TRANSLATION "Enable translations for the Qt frontend" OFF) option(ENABLE_QT_TRANSLATION "Enable translations for the Qt frontend" OFF)
CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_QT "Download bundled Qt binaries" "${MSVC}" "ENABLE_QT" OFF) CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_QT "Download bundled Qt binaries" "${MSVC}" "ENABLE_QT" OFF)
option(ENABLE_WEB_SERVICE "Enable web services (telemetry, etc.)" ON)
option(YUZU_USE_BUNDLED_FFMPEG "Download/Build bundled FFmpeg" "${WIN32}") option(YUZU_USE_BUNDLED_FFMPEG "Download/Build bundled FFmpeg" "${WIN32}")
option(YUZU_USE_EXTERNAL_VULKAN_HEADERS "Use Vulkan-Headers from externals" ON) option(YUZU_USE_EXTERNAL_VULKAN_HEADERS "Use Vulkan-Headers from externals" ON)
@ -141,6 +143,9 @@ if (YUZU_USE_BUNDLED_VCPKG)
if (YUZU_TESTS) if (YUZU_TESTS)
list(APPEND VCPKG_MANIFEST_FEATURES "yuzu-tests") list(APPEND VCPKG_MANIFEST_FEATURES "yuzu-tests")
endif() endif()
if (ENABLE_WEB_SERVICE)
list(APPEND VCPKG_MANIFEST_FEATURES "web-service")
endif()
if (ANDROID) if (ANDROID)
list(APPEND VCPKG_MANIFEST_FEATURES "android") list(APPEND VCPKG_MANIFEST_FEATURES "android")
endif() endif()
@ -340,7 +345,10 @@ if (USE_DISCORD_PRESENCE)
find_package(DiscordRPC MODULE) find_package(DiscordRPC MODULE)
endif() endif()
find_package(httplib 0.12 MODULE COMPONENTS OpenSSL) if (ENABLE_WEB_SERVICE)
find_package(cpp-jwt 1.4 CONFIG)
find_package(httplib 0.12 MODULE COMPONENTS OpenSSL)
endif()
if (YUZU_TESTS) if (YUZU_TESTS)
find_package(Catch2 3.0.1 REQUIRED) find_package(Catch2 3.0.1 REQUIRED)

View File

@ -133,11 +133,19 @@ endif()
add_subdirectory(sirit) add_subdirectory(sirit)
# httplib # httplib
if (NOT TARGET httplib::httplib) if (ENABLE_WEB_SERVICE AND NOT TARGET httplib::httplib)
set(HTTPLIB_REQUIRE_OPENSSL ON) set(HTTPLIB_REQUIRE_OPENSSL ON)
add_subdirectory(cpp-httplib) add_subdirectory(cpp-httplib)
endif() endif()
# cpp-jwt
if (ENABLE_WEB_SERVICE AND NOT TARGET cpp-jwt::cpp-jwt)
set(CPP_JWT_BUILD_EXAMPLES OFF)
set(CPP_JWT_BUILD_TESTS OFF)
set(CPP_JWT_USE_VENDORED_NLOHMANN_JSON OFF)
add_subdirectory(cpp-jwt)
endif()
# Opus # Opus
if (NOT TARGET Opus::opus) if (NOT TARGET Opus::opus)
set(OPUS_BUILD_TESTING OFF) set(OPUS_BUILD_TESTING OFF)

1
externals/cpp-jwt vendored Submodule

@ -0,0 +1 @@
Subproject commit 10ef5735d842b31025f1257ae78899f50a40fb14

View File

@ -208,6 +208,10 @@ if (ENABLE_QT)
add_subdirectory(yuzu) add_subdirectory(yuzu)
endif() endif()
if (ENABLE_WEB_SERVICE)
add_subdirectory(web_service)
endif()
if (ANDROID) if (ANDROID)
add_subdirectory(android/app/src/main/jni) add_subdirectory(android/app/src/main/jni)
target_include_directories(yuzu-android PRIVATE android/app/src/main) target_include_directories(yuzu-android PRIVATE android/app/src/main)

View File

@ -1165,6 +1165,11 @@ if (MINGW)
target_link_libraries(core PRIVATE ${MSWSOCK_LIBRARY}) target_link_libraries(core PRIVATE ${MSWSOCK_LIBRARY})
endif() endif()
if (ENABLE_WEB_SERVICE)
target_compile_definitions(core PRIVATE -DENABLE_WEB_SERVICE)
target_link_libraries(core PRIVATE web_service)
endif()
if (HAS_NCE) if (HAS_NCE)
enable_language(C ASM) enable_language(C ASM)
set(CMAKE_ASM_FLAGS "${CFLAGS} -x assembler-with-cpp") set(CMAKE_ASM_FLAGS "${CFLAGS} -x assembler-with-cpp")

View File

@ -8,6 +8,10 @@ add_executable(yuzu-room
) )
target_link_libraries(yuzu-room PRIVATE common network) target_link_libraries(yuzu-room PRIVATE common network)
if (ENABLE_WEB_SERVICE)
target_compile_definitions(yuzu-room PRIVATE -DENABLE_WEB_SERVICE)
target_link_libraries(yuzu-room PRIVATE web_service)
endif()
target_link_libraries(yuzu-room PRIVATE mbedtls mbedcrypto) target_link_libraries(yuzu-room PRIVATE mbedtls mbedcrypto)
if (MSVC) if (MSVC)

View File

@ -33,6 +33,10 @@
#include "network/room.h" #include "network/room.h"
#include "network/verify_user.h" #include "network/verify_user.h"
#ifdef ENABLE_WEB_SERVICE
#include "web_service/verify_user_jwt.h"
#endif
#undef _UNICODE #undef _UNICODE
#include <getopt.h> #include <getopt.h>
#ifndef _MSC_VER #ifndef _MSC_VER
@ -347,9 +351,14 @@ int main(int argc, char** argv) {
std::unique_ptr<Network::VerifyUser::Backend> verify_backend; std::unique_ptr<Network::VerifyUser::Backend> verify_backend;
if (announce) { if (announce) {
#ifdef ENABLE_WEB_SERVICE
verify_backend =
std::make_unique<WebService::VerifyUserJWT>(Settings::values.web_api_url.GetValue());
#else
LOG_INFO(Network, LOG_INFO(Network,
"yuzu Web Services is not available with this build: validation is disabled."); "yuzu Web Services is not available with this build: validation is disabled.");
verify_backend = std::make_unique<Network::VerifyUser::NullBackend>(); verify_backend = std::make_unique<Network::VerifyUser::NullBackend>();
#endif
} else { } else {
verify_backend = std::make_unique<Network::VerifyUser::NullBackend>(); verify_backend = std::make_unique<Network::VerifyUser::NullBackend>();
} }

View File

@ -20,6 +20,10 @@ add_library(network STATIC
create_target_directory_groups(network) create_target_directory_groups(network)
target_link_libraries(network PRIVATE common enet::enet Boost::headers) target_link_libraries(network PRIVATE common enet::enet Boost::headers)
if (ENABLE_WEB_SERVICE)
target_compile_definitions(network PRIVATE -DENABLE_WEB_SERVICE)
target_link_libraries(network PRIVATE web_service)
endif()
if (YUZU_USE_PRECOMPILED_HEADERS) if (YUZU_USE_PRECOMPILED_HEADERS)
target_precompile_headers(network PRIVATE precompiled_headers.h) target_precompile_headers(network PRIVATE precompiled_headers.h)

View File

@ -9,6 +9,10 @@
#include "common/assert.h" #include "common/assert.h"
#include "network/network.h" #include "network/network.h"
#ifdef ENABLE_WEB_SERVICE
#include "web_service/announce_room_json.h"
#endif
namespace Core { namespace Core {
// Time between room is announced to web_service // Time between room is announced to web_service
@ -16,7 +20,13 @@ static constexpr std::chrono::seconds announce_time_interval(15);
AnnounceMultiplayerSession::AnnounceMultiplayerSession(Network::RoomNetwork& room_network_) AnnounceMultiplayerSession::AnnounceMultiplayerSession(Network::RoomNetwork& room_network_)
: room_network{room_network_} { : room_network{room_network_} {
#ifdef ENABLE_WEB_SERVICE
backend = std::make_unique<WebService::RoomJson>(Settings::values.web_api_url.GetValue(),
Settings::values.yuzu_username.GetValue(),
Settings::values.yuzu_token.GetValue());
#else
backend = std::make_unique<AnnounceMultiplayerRoom::NullBackend>(); backend = std::make_unique<AnnounceMultiplayerRoom::NullBackend>();
#endif
} }
WebService::WebResult AnnounceMultiplayerSession::Register() { WebService::WebResult AnnounceMultiplayerSession::Register() {
@ -142,6 +152,12 @@ bool AnnounceMultiplayerSession::IsRunning() const {
void AnnounceMultiplayerSession::UpdateCredentials() { void AnnounceMultiplayerSession::UpdateCredentials() {
ASSERT_MSG(!IsRunning(), "Credentials can only be updated when session is not running"); ASSERT_MSG(!IsRunning(), "Credentials can only be updated when session is not running");
#ifdef ENABLE_WEB_SERVICE
backend = std::make_unique<WebService::RoomJson>(Settings::values.web_api_url.GetValue(),
Settings::values.yuzu_username.GetValue(),
Settings::values.yuzu_token.GetValue());
#endif
} }
} // namespace Core } // namespace Core

View File

@ -425,6 +425,10 @@ if (USE_DISCORD_PRESENCE)
target_compile_definitions(yuzu PRIVATE -DUSE_DISCORD_PRESENCE) target_compile_definitions(yuzu PRIVATE -DUSE_DISCORD_PRESENCE)
endif() endif()
if (ENABLE_WEB_SERVICE)
target_compile_definitions(yuzu PRIVATE -DENABLE_WEB_SERVICE)
endif()
if (YUZU_USE_QT_MULTIMEDIA) if (YUZU_USE_QT_MULTIMEDIA)
target_link_libraries(yuzu PRIVATE Qt${QT_MAJOR_VERSION}::Multimedia) target_link_libraries(yuzu PRIVATE Qt${QT_MAJOR_VERSION}::Multimedia)
target_compile_definitions(yuzu PRIVATE -DYUZU_USE_QT_MULTIMEDIA) target_compile_definitions(yuzu PRIVATE -DYUZU_USE_QT_MULTIMEDIA)

View File

@ -13,6 +13,9 @@
#include "input_common/drivers/virtual_amiibo.h" #include "input_common/drivers/virtual_amiibo.h"
#include "input_common/main.h" #include "input_common/main.h"
#include "ui_qt_amiibo_settings.h" #include "ui_qt_amiibo_settings.h"
#ifdef ENABLE_WEB_SERVICE
#include "web_service/web_backend.h"
#endif
#include "yuzu/applets/qt_amiibo_settings.h" #include "yuzu/applets/qt_amiibo_settings.h"
#include "yuzu/main.h" #include "yuzu/main.h"
@ -88,6 +91,55 @@ void QtAmiiboSettingsDialog::LoadAmiiboInfo() {
ui->amiiboInfoGroup->setVisible(false); ui->amiiboInfoGroup->setVisible(false);
} }
void QtAmiiboSettingsDialog::LoadAmiiboApiInfo(std::string_view amiibo_id) {
#ifdef ENABLE_WEB_SERVICE
// TODO: Host this data on our website
WebService::Client client{"https://amiiboapi.com", {}, {}};
WebService::Client image_client{"https://raw.githubusercontent.com", {}, {}};
const auto url_path = fmt::format("/api/amiibo/?id={}", amiibo_id);
const auto amiibo_json = client.GetJson(url_path, true).returned_data;
if (amiibo_json.empty()) {
ui->amiiboImageLabel->setVisible(false);
ui->amiiboInfoGroup->setVisible(false);
return;
}
std::string amiibo_series{};
std::string amiibo_name{};
std::string amiibo_image_url{};
std::string amiibo_type{};
const auto parsed_amiibo_json_json = nlohmann::json::parse(amiibo_json).at("amiibo");
parsed_amiibo_json_json.at("amiiboSeries").get_to(amiibo_series);
parsed_amiibo_json_json.at("name").get_to(amiibo_name);
parsed_amiibo_json_json.at("image").get_to(amiibo_image_url);
parsed_amiibo_json_json.at("type").get_to(amiibo_type);
ui->amiiboSeriesValue->setText(QString::fromStdString(amiibo_series));
ui->amiiboNameValue->setText(QString::fromStdString(amiibo_name));
ui->amiiboTypeValue->setText(QString::fromStdString(amiibo_type));
if (amiibo_image_url.size() < 34) {
ui->amiiboImageLabel->setVisible(false);
}
const auto image_url_path = amiibo_image_url.substr(34, amiibo_image_url.size() - 34);
const auto image_data = image_client.GetImage(image_url_path, true).returned_data;
if (image_data.empty()) {
ui->amiiboImageLabel->setVisible(false);
}
QPixmap pixmap;
pixmap.loadFromData(reinterpret_cast<const u8*>(image_data.data()),
static_cast<uint>(image_data.size()));
pixmap = pixmap.scaled(250, 350, Qt::AspectRatioMode::KeepAspectRatio,
Qt::TransformationMode::SmoothTransformation);
ui->amiiboImageLabel->setPixmap(pixmap);
#endif
}
void QtAmiiboSettingsDialog::LoadAmiiboData() { void QtAmiiboSettingsDialog::LoadAmiiboData() {
Service::NFP::RegisterInfo register_info{}; Service::NFP::RegisterInfo register_info{};
Service::NFP::CommonInfo common_info{}; Service::NFP::CommonInfo common_info{};

View File

@ -43,6 +43,7 @@ public:
private: private:
void LoadInfo(); void LoadInfo();
void LoadAmiiboInfo(); void LoadAmiiboInfo();
void LoadAmiiboApiInfo(std::string_view amiibo_id);
void LoadAmiiboData(); void LoadAmiiboData();
void LoadAmiiboGameInfo(); void LoadAmiiboGameInfo();
void SetGameDataName(u32 application_area_id); void SetGameDataName(u32 application_area_id);

View File

@ -21,6 +21,9 @@
#include "yuzu/game_list_p.h" #include "yuzu/game_list_p.h"
#include "yuzu/multiplayer/chat_room.h" #include "yuzu/multiplayer/chat_room.h"
#include "yuzu/multiplayer/message.h" #include "yuzu/multiplayer/message.h"
#ifdef ENABLE_WEB_SERVICE
#include "web_service/web_backend.h"
#endif
class ChatMessage { class ChatMessage {
public: public:
@ -384,6 +387,38 @@ void ChatRoom::SetPlayerList(const Network::RoomMember::MemberList& member_list)
QStandardItem* name_item = new PlayerListItem(member.nickname, member.username, QStandardItem* name_item = new PlayerListItem(member.nickname, member.username,
member.avatar_url, member.game_info); member.avatar_url, member.game_info);
#ifdef ENABLE_WEB_SERVICE
if (!icon_cache.count(member.avatar_url) && !member.avatar_url.empty()) {
// Start a request to get the member's avatar
const QUrl url(QString::fromStdString(member.avatar_url));
QFuture<std::string> future = QtConcurrent::run([url] {
WebService::Client client(
QStringLiteral("%1://%2").arg(url.scheme(), url.host()).toStdString(), "", "");
auto result = client.GetImage(url.path().toStdString(), true);
if (result.returned_data.empty()) {
LOG_ERROR(WebService, "Failed to get avatar");
}
return result.returned_data;
});
auto* future_watcher = new QFutureWatcher<std::string>(this);
connect(future_watcher, &QFutureWatcher<std::string>::finished, this,
[this, future_watcher, avatar_url = member.avatar_url] {
const std::string result = future_watcher->result();
if (result.empty())
return;
QPixmap pixmap;
if (!pixmap.loadFromData(reinterpret_cast<const u8*>(result.data()),
static_cast<uint>(result.size())))
return;
icon_cache[avatar_url] =
pixmap.scaled(48, 48, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
// Update all the displayed icons with the new icon_cache
UpdateIconDisplay();
});
future_watcher->setFuture(future);
}
#endif
player_list->invisibleRootItem()->appendRow(name_item); player_list->invisibleRootItem()->appendRow(name_item);
} }
UpdateIconDisplay(); UpdateIconDisplay();

View File

@ -23,6 +23,9 @@
#include "yuzu/multiplayer/state.h" #include "yuzu/multiplayer/state.h"
#include "yuzu/multiplayer/validation.h" #include "yuzu/multiplayer/validation.h"
#include "yuzu/uisettings.h" #include "yuzu/uisettings.h"
#ifdef ENABLE_WEB_SERVICE
#include "web_service/verify_user_jwt.h"
#endif
HostRoomWindow::HostRoomWindow(QWidget* parent, QStandardItemModel* list, HostRoomWindow::HostRoomWindow(QWidget* parent, QStandardItemModel* list,
std::shared_ptr<Core::AnnounceMultiplayerSession> session, std::shared_ptr<Core::AnnounceMultiplayerSession> session,
@ -95,7 +98,12 @@ std::unique_ptr<Network::VerifyUser::Backend> HostRoomWindow::CreateVerifyBacken
bool use_validation) const { bool use_validation) const {
std::unique_ptr<Network::VerifyUser::Backend> verify_backend; std::unique_ptr<Network::VerifyUser::Backend> verify_backend;
if (use_validation) { if (use_validation) {
#ifdef ENABLE_WEB_SERVICE
verify_backend =
std::make_unique<WebService::VerifyUserJWT>(Settings::values.web_api_url.GetValue());
#else
verify_backend = std::make_unique<Network::VerifyUser::NullBackend>(); verify_backend = std::make_unique<Network::VerifyUser::NullBackend>();
#endif
} else { } else {
verify_backend = std::make_unique<Network::VerifyUser::NullBackend>(); verify_backend = std::make_unique<Network::VerifyUser::NullBackend>();
} }
@ -193,6 +201,21 @@ void HostRoomWindow::Host() {
} }
} }
std::string token; std::string token;
#ifdef ENABLE_WEB_SERVICE
if (is_public) {
WebService::Client client(Settings::values.web_api_url.GetValue(),
Settings::values.yuzu_username.GetValue(),
Settings::values.yuzu_token.GetValue());
if (auto room = room_network.GetRoom().lock()) {
token = client.GetExternalJWT(room->GetVerifyUID()).returned_data;
}
if (token.empty()) {
LOG_ERROR(WebService, "Could not get external JWT, verification may fail");
} else {
LOG_INFO(WebService, "Successfully requested external JWT: size={}", token.size());
}
}
#endif
// TODO: Check what to do with this // TODO: Check what to do with this
member->Join(ui->username->text().toStdString(), "127.0.0.1", port, 0, member->Join(ui->username->text().toStdString(), "127.0.0.1", port, 0,
Network::NoPreferredIP, password, token); Network::NoPreferredIP, password, token);

View File

@ -20,6 +20,9 @@
#include "yuzu/multiplayer/state.h" #include "yuzu/multiplayer/state.h"
#include "yuzu/multiplayer/validation.h" #include "yuzu/multiplayer/validation.h"
#include "yuzu/uisettings.h" #include "yuzu/uisettings.h"
#ifdef ENABLE_WEB_SERVICE
#include "web_service/web_backend.h"
#endif
Lobby::Lobby(QWidget* parent, QStandardItemModel* list, Lobby::Lobby(QWidget* parent, QStandardItemModel* list,
std::shared_ptr<Core::AnnounceMultiplayerSession> session, Core::System& system_) std::shared_ptr<Core::AnnounceMultiplayerSession> session, Core::System& system_)
@ -183,6 +186,20 @@ void Lobby::OnJoinRoom(const QModelIndex& source) {
// attempt to connect in a different thread // attempt to connect in a different thread
QFuture<void> f = QtConcurrent::run([nickname, ip, port, password, verify_uid, this] { QFuture<void> f = QtConcurrent::run([nickname, ip, port, password, verify_uid, this] {
std::string token; std::string token;
#ifdef ENABLE_WEB_SERVICE
if (!Settings::values.yuzu_username.GetValue().empty() &&
!Settings::values.yuzu_token.GetValue().empty()) {
WebService::Client client(Settings::values.web_api_url.GetValue(),
Settings::values.yuzu_username.GetValue(),
Settings::values.yuzu_token.GetValue());
token = client.GetExternalJWT(verify_uid).returned_data;
if (token.empty()) {
LOG_ERROR(WebService, "Could not get external JWT, verification may fail");
} else {
LOG_INFO(WebService, "Successfully requested external JWT: size={}", token.size());
}
}
#endif
if (auto room_member = room_network.GetRoomMember().lock()) { if (auto room_member = room_network.GetRoomMember().lock()) {
room_member->Join(nickname, ip.c_str(), port, 0, Network::NoPreferredIP, password, room_member->Join(nickname, ip.c_str(), port, 0, Network::NoPreferredIP, password,
token); token);