diff options
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/CMakeLists.txt | 14 | ||||
-rw-r--r-- | src/core/announce_multiplayer_session.cpp | 164 | ||||
-rw-r--r-- | src/core/announce_multiplayer_session.h | 98 | ||||
-rw-r--r-- | src/core/core.cpp | 31 | ||||
-rw-r--r-- | src/core/core.h | 10 | ||||
-rw-r--r-- | src/core/hle/service/nifm/nifm.cpp | 4 | ||||
-rw-r--r-- | src/core/hle/service/sockets/bsd.cpp | 4 | ||||
-rw-r--r-- | src/core/hle/service/sockets/bsd.h | 2 | ||||
-rw-r--r-- | src/core/hle/service/sockets/sockets_translate.cpp | 2 | ||||
-rw-r--r-- | src/core/hle/service/sockets/sockets_translate.h | 2 | ||||
-rw-r--r-- | src/core/internal_network/network.cpp (renamed from src/core/network/network.cpp) | 6 | ||||
-rw-r--r-- | src/core/internal_network/network.h (renamed from src/core/network/network.h) | 0 | ||||
-rw-r--r-- | src/core/internal_network/network_interface.cpp (renamed from src/core/network/network_interface.cpp) | 2 | ||||
-rw-r--r-- | src/core/internal_network/network_interface.h (renamed from src/core/network/network_interface.h) | 0 | ||||
-rw-r--r-- | src/core/internal_network/sockets.h (renamed from src/core/network/sockets.h) | 3 |
15 files changed, 322 insertions, 20 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 32cc2f392..c1cc62a45 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -1,4 +1,6 @@ add_library(core STATIC + announce_multiplayer_session.cpp + announce_multiplayer_session.h arm/arm_interface.h arm/arm_interface.cpp arm/cpu_interrupt_handler.cpp @@ -714,6 +716,11 @@ add_library(core STATIC hle/service/vi/vi_u.h hle/service/wlan/wlan.cpp hle/service/wlan/wlan.h + internal_network/network.cpp + internal_network/network.h + internal_network/network_interface.cpp + internal_network/network_interface.h + internal_network/sockets.h loader/deconstructed_rom_directory.cpp loader/deconstructed_rom_directory.h loader/elf.cpp @@ -741,11 +748,6 @@ add_library(core STATIC memory/dmnt_cheat_vm.h memory.cpp memory.h - network/network.cpp - network/network.h - network/network_interface.cpp - network/network_interface.h - network/sockets.h perf_stats.cpp perf_stats.h reporter.cpp @@ -780,7 +782,7 @@ endif() create_target_directory_groups(core) -target_link_libraries(core PUBLIC common PRIVATE audio_core video_core) +target_link_libraries(core PUBLIC common PRIVATE audio_core network video_core) target_link_libraries(core PUBLIC Boost::boost PRIVATE fmt::fmt nlohmann_json::nlohmann_json mbedtls Opus::Opus) if (MINGW) target_link_libraries(core PRIVATE ${MSWSOCK_LIBRARY}) diff --git a/src/core/announce_multiplayer_session.cpp b/src/core/announce_multiplayer_session.cpp new file mode 100644 index 000000000..d73a488cf --- /dev/null +++ b/src/core/announce_multiplayer_session.cpp @@ -0,0 +1,164 @@ +// SPDX-FileCopyrightText: Copyright 2017 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include <chrono> +#include <future> +#include <vector> +#include "announce_multiplayer_session.h" +#include "common/announce_multiplayer_room.h" +#include "common/assert.h" +#include "common/settings.h" +#include "network/network.h" + +#ifdef ENABLE_WEB_SERVICE +#include "web_service/announce_room_json.h" +#endif + +namespace Core { + +// Time between room is announced to web_service +static constexpr std::chrono::seconds announce_time_interval(15); + +AnnounceMultiplayerSession::AnnounceMultiplayerSession(Network::RoomNetwork& 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>(); +#endif +} + +WebService::WebResult AnnounceMultiplayerSession::Register() { + std::shared_ptr<Network::Room> room = room_network.GetRoom().lock(); + if (!room) { + return WebService::WebResult{WebService::WebResult::Code::LibError, + "Network is not initialized", ""}; + } + if (room->GetState() != Network::Room::State::Open) { + return WebService::WebResult{WebService::WebResult::Code::LibError, "Room is not open", ""}; + } + UpdateBackendData(room); + WebService::WebResult result = backend->Register(); + if (result.result_code != WebService::WebResult::Code::Success) { + return result; + } + LOG_INFO(WebService, "Room has been registered"); + room->SetVerifyUID(result.returned_data); + registered = true; + return WebService::WebResult{WebService::WebResult::Code::Success, "", ""}; +} + +void AnnounceMultiplayerSession::Start() { + if (announce_multiplayer_thread) { + Stop(); + } + shutdown_event.Reset(); + announce_multiplayer_thread = + std::make_unique<std::thread>(&AnnounceMultiplayerSession::AnnounceMultiplayerLoop, this); +} + +void AnnounceMultiplayerSession::Stop() { + if (announce_multiplayer_thread) { + shutdown_event.Set(); + announce_multiplayer_thread->join(); + announce_multiplayer_thread.reset(); + backend->Delete(); + registered = false; + } +} + +AnnounceMultiplayerSession::CallbackHandle AnnounceMultiplayerSession::BindErrorCallback( + std::function<void(const WebService::WebResult&)> function) { + std::lock_guard lock(callback_mutex); + auto handle = std::make_shared<std::function<void(const WebService::WebResult&)>>(function); + error_callbacks.insert(handle); + return handle; +} + +void AnnounceMultiplayerSession::UnbindErrorCallback(CallbackHandle handle) { + std::lock_guard lock(callback_mutex); + error_callbacks.erase(handle); +} + +AnnounceMultiplayerSession::~AnnounceMultiplayerSession() { + Stop(); +} + +void AnnounceMultiplayerSession::UpdateBackendData(std::shared_ptr<Network::Room> room) { + Network::RoomInformation room_information = room->GetRoomInformation(); + std::vector<AnnounceMultiplayerRoom::Member> memberlist = room->GetRoomMemberList(); + backend->SetRoomInformation(room_information.name, room_information.description, + room_information.port, room_information.member_slots, + Network::network_version, room->HasPassword(), + room_information.preferred_game); + backend->ClearPlayers(); + for (const auto& member : memberlist) { + backend->AddPlayer(member); + } +} + +void AnnounceMultiplayerSession::AnnounceMultiplayerLoop() { + // Invokes all current bound error callbacks. + const auto ErrorCallback = [this](WebService::WebResult result) { + std::lock_guard<std::mutex> lock(callback_mutex); + for (auto callback : error_callbacks) { + (*callback)(result); + } + }; + + if (!registered) { + WebService::WebResult result = Register(); + if (result.result_code != WebService::WebResult::Code::Success) { + ErrorCallback(result); + return; + } + } + + auto update_time = std::chrono::steady_clock::now(); + std::future<WebService::WebResult> future; + while (!shutdown_event.WaitUntil(update_time)) { + update_time += announce_time_interval; + std::shared_ptr<Network::Room> room = room_network.GetRoom().lock(); + if (!room) { + break; + } + if (room->GetState() != Network::Room::State::Open) { + break; + } + UpdateBackendData(room); + WebService::WebResult result = backend->Update(); + if (result.result_code != WebService::WebResult::Code::Success) { + ErrorCallback(result); + } + if (result.result_string == "404") { + registered = false; + // Needs to register the room again + WebService::WebResult register_result = Register(); + if (register_result.result_code != WebService::WebResult::Code::Success) { + ErrorCallback(register_result); + } + } + } +} + +AnnounceMultiplayerRoom::RoomList AnnounceMultiplayerSession::GetRoomList() { + return backend->GetRoomList(); +} + +bool AnnounceMultiplayerSession::IsRunning() const { + return announce_multiplayer_thread != nullptr; +} + +void AnnounceMultiplayerSession::UpdateCredentials() { + 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 diff --git a/src/core/announce_multiplayer_session.h b/src/core/announce_multiplayer_session.h new file mode 100644 index 000000000..db790f7d2 --- /dev/null +++ b/src/core/announce_multiplayer_session.h @@ -0,0 +1,98 @@ +// SPDX-FileCopyrightText: Copyright 2017 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include <atomic> +#include <functional> +#include <memory> +#include <mutex> +#include <set> +#include <thread> +#include "common/announce_multiplayer_room.h" +#include "common/common_types.h" +#include "common/thread.h" + +namespace Network { +class Room; +class RoomNetwork; +} // namespace Network + +namespace Core { + +/** + * Instruments AnnounceMultiplayerRoom::Backend. + * Creates a thread that regularly updates the room information and submits them + * An async get of room information is also possible + */ +class AnnounceMultiplayerSession { +public: + using CallbackHandle = std::shared_ptr<std::function<void(const WebService::WebResult&)>>; + AnnounceMultiplayerSession(Network::RoomNetwork& room_network_); + ~AnnounceMultiplayerSession(); + + /** + * Allows to bind a function that will get called if the announce encounters an error + * @param function The function that gets called + * @return A handle that can be used the unbind the function + */ + CallbackHandle BindErrorCallback(std::function<void(const WebService::WebResult&)> function); + + /** + * Unbind a function from the error callbacks + * @param handle The handle for the function that should get unbind + */ + void UnbindErrorCallback(CallbackHandle handle); + + /** + * Registers a room to web services + * @return The result of the registration attempt. + */ + WebService::WebResult Register(); + + /** + * Starts the announce of a room to web services + */ + void Start(); + + /** + * Stops the announce to web services + */ + void Stop(); + + /** + * Returns a list of all room information the backend got + * @param func A function that gets executed when the async get finished, e.g. a signal + * @return a list of rooms received from the web service + */ + AnnounceMultiplayerRoom::RoomList GetRoomList(); + + /** + * Whether the announce session is still running + */ + bool IsRunning() const; + + /** + * Recreates the backend, updating the credentials. + * This can only be used when the announce session is not running. + */ + void UpdateCredentials(); + +private: + void UpdateBackendData(std::shared_ptr<Network::Room> room); + void AnnounceMultiplayerLoop(); + + Common::Event shutdown_event; + std::mutex callback_mutex; + std::set<CallbackHandle> error_callbacks; + std::unique_ptr<std::thread> announce_multiplayer_thread; + + /// Backend interface that logs fields + std::unique_ptr<AnnounceMultiplayerRoom::Backend> backend; + + std::atomic_bool registered = false; ///< Whether the room has been registered + + Network::RoomNetwork& room_network; +}; + +} // namespace Core diff --git a/src/core/core.cpp b/src/core/core.cpp index 0ede0d85c..95791a07f 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -43,14 +43,15 @@ #include "core/hle/service/service.h" #include "core/hle/service/sm/sm.h" #include "core/hle/service/time/time_manager.h" +#include "core/internal_network/network.h" #include "core/loader/loader.h" #include "core/memory.h" #include "core/memory/cheat_engine.h" -#include "core/network/network.h" #include "core/perf_stats.h" #include "core/reporter.h" #include "core/telemetry_session.h" #include "core/tools/freezer.h" +#include "network/network.h" #include "video_core/renderer_base.h" #include "video_core/video_core.h" @@ -130,7 +131,7 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs, struct System::Impl { explicit Impl(System& system) - : kernel{system}, fs_controller{system}, memory{system}, hid_core{}, + : kernel{system}, fs_controller{system}, memory{system}, hid_core{}, room_network{}, cpu_manager{system}, reporter{system}, applet_manager{system}, time_manager{system} {} SystemResultStatus Run() { @@ -315,6 +316,17 @@ struct System::Impl { GetAndResetPerfStats(); perf_stats->BeginSystemFrame(); + std::string name = "Unknown Game"; + if (app_loader->ReadTitle(name) != Loader::ResultStatus::Success) { + LOG_ERROR(Core, "Failed to read title for ROM (Error {})", load_result); + } + if (auto room_member = room_network.GetRoomMember().lock()) { + Network::GameInfo game_info; + game_info.name = name; + game_info.id = program_id; + room_member->SendGameInfo(game_info); + } + status = SystemResultStatus::Success; return status; } @@ -362,6 +374,11 @@ struct System::Impl { memory.Reset(); applet_manager.ClearAll(); + if (auto room_member = room_network.GetRoomMember().lock()) { + Network::GameInfo game_info{}; + room_member->SendGameInfo(game_info); + } + LOG_DEBUG(Core, "Shutdown OK"); } @@ -434,6 +451,8 @@ struct System::Impl { std::unique_ptr<AudioCore::AudioCore> audio_core; Core::Memory::Memory memory; Core::HID::HIDCore hid_core; + Network::RoomNetwork room_network; + CpuManager cpu_manager; std::atomic_bool is_powered_on{}; bool exit_lock = false; @@ -879,6 +898,14 @@ const Core::Debugger& System::GetDebugger() const { return *impl->debugger; } +Network::RoomNetwork& System::GetRoomNetwork() { + return impl->room_network; +} + +const Network::RoomNetwork& System::GetRoomNetwork() const { + return impl->room_network; +} + void System::RegisterExecuteProgramCallback(ExecuteProgramCallback&& callback) { impl->execute_program_callback = std::move(callback); } diff --git a/src/core/core.h b/src/core/core.h index a49d1214b..13122dd61 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -97,6 +97,10 @@ namespace Core::HID { class HIDCore; } +namespace Network { +class RoomNetwork; +} + namespace Core { class ARM_Interface; @@ -379,6 +383,12 @@ public: [[nodiscard]] Core::Debugger& GetDebugger(); [[nodiscard]] const Core::Debugger& GetDebugger() const; + /// Gets a mutable reference to the Room Network. + [[nodiscard]] Network::RoomNetwork& GetRoomNetwork(); + + /// Gets an immutable reference to the Room Network. + [[nodiscard]] const Network::RoomNetwork& GetRoomNetwork() const; + void SetExitLock(bool locked); [[nodiscard]] bool GetExitLock() const; diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp index 7055ea93e..2889973e4 100644 --- a/src/core/hle/service/nifm/nifm.cpp +++ b/src/core/hle/service/nifm/nifm.cpp @@ -18,8 +18,8 @@ namespace { } // Anonymous namespace -#include "core/network/network.h" -#include "core/network/network_interface.h" +#include "core/internal_network/network.h" +#include "core/internal_network/network_interface.h" namespace Service::NIFM { diff --git a/src/core/hle/service/sockets/bsd.cpp b/src/core/hle/service/sockets/bsd.cpp index 3e9dc4a13..c7194731e 100644 --- a/src/core/hle/service/sockets/bsd.cpp +++ b/src/core/hle/service/sockets/bsd.cpp @@ -13,8 +13,8 @@ #include "core/hle/kernel/k_thread.h" #include "core/hle/service/sockets/bsd.h" #include "core/hle/service/sockets/sockets_translate.h" -#include "core/network/network.h" -#include "core/network/sockets.h" +#include "core/internal_network/network.h" +#include "core/internal_network/sockets.h" namespace Service::Sockets { diff --git a/src/core/hle/service/sockets/bsd.h b/src/core/hle/service/sockets/bsd.h index fed740d87..9ea36428d 100644 --- a/src/core/hle/service/sockets/bsd.h +++ b/src/core/hle/service/sockets/bsd.h @@ -16,7 +16,7 @@ class System; namespace Network { class Socket; -} +} // namespace Network namespace Service::Sockets { diff --git a/src/core/hle/service/sockets/sockets_translate.cpp b/src/core/hle/service/sockets/sockets_translate.cpp index 9c0936d97..2db10ec81 100644 --- a/src/core/hle/service/sockets/sockets_translate.cpp +++ b/src/core/hle/service/sockets/sockets_translate.cpp @@ -7,7 +7,7 @@ #include "common/common_types.h" #include "core/hle/service/sockets/sockets.h" #include "core/hle/service/sockets/sockets_translate.h" -#include "core/network/network.h" +#include "core/internal_network/network.h" namespace Service::Sockets { diff --git a/src/core/hle/service/sockets/sockets_translate.h b/src/core/hle/service/sockets/sockets_translate.h index 5e9809add..c93291d3e 100644 --- a/src/core/hle/service/sockets/sockets_translate.h +++ b/src/core/hle/service/sockets/sockets_translate.h @@ -7,7 +7,7 @@ #include "common/common_types.h" #include "core/hle/service/sockets/sockets.h" -#include "core/network/network.h" +#include "core/internal_network/network.h" namespace Service::Sockets { diff --git a/src/core/network/network.cpp b/src/core/internal_network/network.cpp index fdafbea92..36c43cc8f 100644 --- a/src/core/network/network.cpp +++ b/src/core/internal_network/network.cpp @@ -29,9 +29,9 @@ #include "common/common_types.h" #include "common/logging/log.h" #include "common/settings.h" -#include "core/network/network.h" -#include "core/network/network_interface.h" -#include "core/network/sockets.h" +#include "core/internal_network/network.h" +#include "core/internal_network/network_interface.h" +#include "core/internal_network/sockets.h" namespace Network { diff --git a/src/core/network/network.h b/src/core/internal_network/network.h index 10e5ef10d..10e5ef10d 100644 --- a/src/core/network/network.h +++ b/src/core/internal_network/network.h diff --git a/src/core/network/network_interface.cpp b/src/core/internal_network/network_interface.cpp index 15ecc6abf..0f0a66160 100644 --- a/src/core/network/network_interface.cpp +++ b/src/core/internal_network/network_interface.cpp @@ -11,7 +11,7 @@ #include "common/logging/log.h" #include "common/settings.h" #include "common/string_util.h" -#include "core/network/network_interface.h" +#include "core/internal_network/network_interface.h" #ifdef _WIN32 #include <iphlpapi.h> diff --git a/src/core/network/network_interface.h b/src/core/internal_network/network_interface.h index 9b98b6b42..9b98b6b42 100644 --- a/src/core/network/network_interface.h +++ b/src/core/internal_network/network_interface.h diff --git a/src/core/network/sockets.h b/src/core/internal_network/sockets.h index f889159f5..77e27e928 100644 --- a/src/core/network/sockets.h +++ b/src/core/internal_network/sockets.h @@ -3,6 +3,7 @@ #pragma once +#include <map> #include <memory> #include <utility> @@ -12,7 +13,7 @@ #endif #include "common/common_types.h" -#include "core/network/network.h" +#include "core/internal_network/network.h" // TODO: C++20 Replace std::vector usages with std::span |