summaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/CMakeLists.txt14
-rw-r--r--src/core/announce_multiplayer_session.cpp165
-rw-r--r--src/core/announce_multiplayer_session.h96
-rw-r--r--src/core/core.cpp17
-rw-r--r--src/core/hle/service/nifm/nifm.cpp4
-rw-r--r--src/core/hle/service/sockets/bsd.cpp4
-rw-r--r--src/core/hle/service/sockets/bsd.h2
-rw-r--r--src/core/hle/service/sockets/sockets_translate.cpp2
-rw-r--r--src/core/hle/service/sockets/sockets_translate.h2
-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
14 files changed, 298 insertions, 19 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 32cc2f392..48f5c1ee0 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
@@ -741,11 +743,11 @@ 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
+ internal_network/network.cpp
+ internal_network/network.h
+ internal_network/network_interface.cpp
+ internal_network/network_interface.h
+ internal_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..a680ad202
--- /dev/null
+++ b/src/core/announce_multiplayer_session.cpp
@@ -0,0 +1,165 @@
+// Copyright 2017 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#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() {
+#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 = 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<Network::Room::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, room_information.preferred_game_id);
+ backend->ClearPlayers();
+ for (const auto& member : memberlist) {
+ backend->AddPlayer(member.username, member.nickname, member.avatar_url, member.mac_address,
+ member.game_info.id, member.game_info.name);
+ }
+}
+
+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 = 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..2aaf55017
--- /dev/null
+++ b/src/core/announce_multiplayer_session.h
@@ -0,0 +1,96 @@
+// Copyright 2017 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#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;
+}
+
+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();
+ ~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:
+ 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
+
+ void UpdateBackendData(std::shared_ptr<Network::Room> room);
+ void AnnounceMultiplayerLoop();
+};
+
+} // namespace Core
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 0ede0d85c..5df32c1e7 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"
@@ -315,6 +316,15 @@ struct System::Impl {
GetAndResetPerfStats();
perf_stats->BeginSystemFrame();
+ std::string name = "Unknown Game";
+ const Loader::ResultStatus res{app_loader->ReadTitle(name)};
+ if (auto room_member = 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 +372,11 @@ struct System::Impl {
memory.Reset();
applet_manager.ClearAll();
+ if (auto room_member = Network::GetRoomMember().lock()) {
+ Network::GameInfo game_info{};
+ room_member->SendGameInfo(game_info);
+ }
+
LOG_DEBUG(Core, "Shutdown OK");
}
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