summaryrefslogtreecommitdiff
path: root/src/network
diff options
context:
space:
mode:
authorGravatar FearlessTobi2022-08-16 23:13:05 +0200
committerGravatar FearlessTobi2022-08-27 03:02:21 +0200
commitb904652d69fb3d3bf1918a7dd7f04bc049c9f460 (patch)
tree4a252395a2a51d8998ef088e446c1f9a7f238aa3 /src/network
parentMerge pull request #8566 from german77/galaxy (diff)
downloadyuzu-b904652d69fb3d3bf1918a7dd7f04bc049c9f460.tar.gz
yuzu-b904652d69fb3d3bf1918a7dd7f04bc049c9f460.tar.xz
yuzu-b904652d69fb3d3bf1918a7dd7f04bc049c9f460.zip
yuzu_room: Remove dependency on core
Diffstat (limited to 'src/network')
-rw-r--r--src/network/CMakeLists.txt6
-rw-r--r--src/network/announce_multiplayer_session.cpp164
-rw-r--r--src/network/announce_multiplayer_session.h98
3 files changed, 268 insertions, 0 deletions
diff --git a/src/network/CMakeLists.txt b/src/network/CMakeLists.txt
index 312f79b68..6f8ca4b90 100644
--- a/src/network/CMakeLists.txt
+++ b/src/network/CMakeLists.txt
@@ -2,6 +2,8 @@
2# SPDX-License-Identifier: GPL-3.0-or-later 2# SPDX-License-Identifier: GPL-3.0-or-later
3 3
4add_library(network STATIC 4add_library(network STATIC
5 announce_multiplayer_session.cpp
6 announce_multiplayer_session.h
5 network.cpp 7 network.cpp
6 network.h 8 network.h
7 packet.cpp 9 packet.cpp
@@ -17,3 +19,7 @@ add_library(network STATIC
17create_target_directory_groups(network) 19create_target_directory_groups(network)
18 20
19target_link_libraries(network PRIVATE common enet Boost::boost) 21target_link_libraries(network PRIVATE common enet Boost::boost)
22if (ENABLE_WEB_SERVICE)
23 target_compile_definitions(network PRIVATE -DENABLE_WEB_SERVICE)
24 target_link_libraries(network PRIVATE web_service)
25endif()
diff --git a/src/network/announce_multiplayer_session.cpp b/src/network/announce_multiplayer_session.cpp
new file mode 100644
index 000000000..6737ce85a
--- /dev/null
+++ b/src/network/announce_multiplayer_session.cpp
@@ -0,0 +1,164 @@
1// SPDX-FileCopyrightText: Copyright 2017 Citra Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include <chrono>
5#include <future>
6#include <vector>
7#include "announce_multiplayer_session.h"
8#include "common/announce_multiplayer_room.h"
9#include "common/assert.h"
10#include "common/settings.h"
11#include "network/network.h"
12
13#ifdef ENABLE_WEB_SERVICE
14#include "web_service/announce_room_json.h"
15#endif
16
17namespace Core {
18
19// Time between room is announced to web_service
20static constexpr std::chrono::seconds announce_time_interval(15);
21
22AnnounceMultiplayerSession::AnnounceMultiplayerSession(Network::RoomNetwork& room_network_)
23 : room_network{room_network_} {
24#ifdef ENABLE_WEB_SERVICE
25 backend = std::make_unique<WebService::RoomJson>(Settings::values.web_api_url.GetValue(),
26 Settings::values.yuzu_username.GetValue(),
27 Settings::values.yuzu_token.GetValue());
28#else
29 backend = std::make_unique<AnnounceMultiplayerRoom::NullBackend>();
30#endif
31}
32
33WebService::WebResult AnnounceMultiplayerSession::Register() {
34 auto room = room_network.GetRoom().lock();
35 if (!room) {
36 return WebService::WebResult{WebService::WebResult::Code::LibError,
37 "Network is not initialized", ""};
38 }
39 if (room->GetState() != Network::Room::State::Open) {
40 return WebService::WebResult{WebService::WebResult::Code::LibError, "Room is not open", ""};
41 }
42 UpdateBackendData(room);
43 WebService::WebResult result = backend->Register();
44 if (result.result_code != WebService::WebResult::Code::Success) {
45 return result;
46 }
47 LOG_INFO(WebService, "Room has been registered");
48 room->SetVerifyUID(result.returned_data);
49 registered = true;
50 return WebService::WebResult{WebService::WebResult::Code::Success, "", ""};
51}
52
53void AnnounceMultiplayerSession::Start() {
54 if (announce_multiplayer_thread) {
55 Stop();
56 }
57 shutdown_event.Reset();
58 announce_multiplayer_thread =
59 std::make_unique<std::thread>(&AnnounceMultiplayerSession::AnnounceMultiplayerLoop, this);
60}
61
62void AnnounceMultiplayerSession::Stop() {
63 if (announce_multiplayer_thread) {
64 shutdown_event.Set();
65 announce_multiplayer_thread->join();
66 announce_multiplayer_thread.reset();
67 backend->Delete();
68 registered = false;
69 }
70}
71
72AnnounceMultiplayerSession::CallbackHandle AnnounceMultiplayerSession::BindErrorCallback(
73 std::function<void(const WebService::WebResult&)> function) {
74 std::lock_guard lock(callback_mutex);
75 auto handle = std::make_shared<std::function<void(const WebService::WebResult&)>>(function);
76 error_callbacks.insert(handle);
77 return handle;
78}
79
80void AnnounceMultiplayerSession::UnbindErrorCallback(CallbackHandle handle) {
81 std::lock_guard lock(callback_mutex);
82 error_callbacks.erase(handle);
83}
84
85AnnounceMultiplayerSession::~AnnounceMultiplayerSession() {
86 Stop();
87}
88
89void AnnounceMultiplayerSession::UpdateBackendData(std::shared_ptr<Network::Room> room) {
90 Network::RoomInformation room_information = room->GetRoomInformation();
91 std::vector<AnnounceMultiplayerRoom::Member> memberlist = room->GetRoomMemberList();
92 backend->SetRoomInformation(room_information.name, room_information.description,
93 room_information.port, room_information.member_slots,
94 Network::network_version, room->HasPassword(),
95 room_information.preferred_game);
96 backend->ClearPlayers();
97 for (const auto& member : memberlist) {
98 backend->AddPlayer(member);
99 }
100}
101
102void AnnounceMultiplayerSession::AnnounceMultiplayerLoop() {
103 // Invokes all current bound error callbacks.
104 const auto ErrorCallback = [this](WebService::WebResult result) {
105 std::lock_guard lock(callback_mutex);
106 for (auto callback : error_callbacks) {
107 (*callback)(result);
108 }
109 };
110
111 if (!registered) {
112 WebService::WebResult result = Register();
113 if (result.result_code != WebService::WebResult::Code::Success) {
114 ErrorCallback(result);
115 return;
116 }
117 }
118
119 auto update_time = std::chrono::steady_clock::now();
120 std::future<WebService::WebResult> future;
121 while (!shutdown_event.WaitUntil(update_time)) {
122 update_time += announce_time_interval;
123 auto room = room_network.GetRoom().lock();
124 if (!room) {
125 break;
126 }
127 if (room->GetState() != Network::Room::State::Open) {
128 break;
129 }
130 UpdateBackendData(room);
131 WebService::WebResult result = backend->Update();
132 if (result.result_code != WebService::WebResult::Code::Success) {
133 ErrorCallback(result);
134 }
135 if (result.result_string == "404") {
136 registered = false;
137 // Needs to register the room again
138 WebService::WebResult register_result = Register();
139 if (register_result.result_code != WebService::WebResult::Code::Success) {
140 ErrorCallback(register_result);
141 }
142 }
143 }
144}
145
146AnnounceMultiplayerRoom::RoomList AnnounceMultiplayerSession::GetRoomList() {
147 return backend->GetRoomList();
148}
149
150bool AnnounceMultiplayerSession::IsRunning() const {
151 return announce_multiplayer_thread != nullptr;
152}
153
154void AnnounceMultiplayerSession::UpdateCredentials() {
155 ASSERT_MSG(!IsRunning(), "Credentials can only be updated when session is not running");
156
157#ifdef ENABLE_WEB_SERVICE
158 backend = std::make_unique<WebService::RoomJson>(Settings::values.web_api_url.GetValue(),
159 Settings::values.yuzu_username.GetValue(),
160 Settings::values.yuzu_token.GetValue());
161#endif
162}
163
164} // namespace Core
diff --git a/src/network/announce_multiplayer_session.h b/src/network/announce_multiplayer_session.h
new file mode 100644
index 000000000..db790f7d2
--- /dev/null
+++ b/src/network/announce_multiplayer_session.h
@@ -0,0 +1,98 @@
1// SPDX-FileCopyrightText: Copyright 2017 Citra Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include <atomic>
7#include <functional>
8#include <memory>
9#include <mutex>
10#include <set>
11#include <thread>
12#include "common/announce_multiplayer_room.h"
13#include "common/common_types.h"
14#include "common/thread.h"
15
16namespace Network {
17class Room;
18class RoomNetwork;
19} // namespace Network
20
21namespace Core {
22
23/**
24 * Instruments AnnounceMultiplayerRoom::Backend.
25 * Creates a thread that regularly updates the room information and submits them
26 * An async get of room information is also possible
27 */
28class AnnounceMultiplayerSession {
29public:
30 using CallbackHandle = std::shared_ptr<std::function<void(const WebService::WebResult&)>>;
31 AnnounceMultiplayerSession(Network::RoomNetwork& room_network_);
32 ~AnnounceMultiplayerSession();
33
34 /**
35 * Allows to bind a function that will get called if the announce encounters an error
36 * @param function The function that gets called
37 * @return A handle that can be used the unbind the function
38 */
39 CallbackHandle BindErrorCallback(std::function<void(const WebService::WebResult&)> function);
40
41 /**
42 * Unbind a function from the error callbacks
43 * @param handle The handle for the function that should get unbind
44 */
45 void UnbindErrorCallback(CallbackHandle handle);
46
47 /**
48 * Registers a room to web services
49 * @return The result of the registration attempt.
50 */
51 WebService::WebResult Register();
52
53 /**
54 * Starts the announce of a room to web services
55 */
56 void Start();
57
58 /**
59 * Stops the announce to web services
60 */
61 void Stop();
62
63 /**
64 * Returns a list of all room information the backend got
65 * @param func A function that gets executed when the async get finished, e.g. a signal
66 * @return a list of rooms received from the web service
67 */
68 AnnounceMultiplayerRoom::RoomList GetRoomList();
69
70 /**
71 * Whether the announce session is still running
72 */
73 bool IsRunning() const;
74
75 /**
76 * Recreates the backend, updating the credentials.
77 * This can only be used when the announce session is not running.
78 */
79 void UpdateCredentials();
80
81private:
82 void UpdateBackendData(std::shared_ptr<Network::Room> room);
83 void AnnounceMultiplayerLoop();
84
85 Common::Event shutdown_event;
86 std::mutex callback_mutex;
87 std::set<CallbackHandle> error_callbacks;
88 std::unique_ptr<std::thread> announce_multiplayer_thread;
89
90 /// Backend interface that logs fields
91 std::unique_ptr<AnnounceMultiplayerRoom::Backend> backend;
92
93 std::atomic_bool registered = false; ///< Whether the room has been registered
94
95 Network::RoomNetwork& room_network;
96};
97
98} // namespace Core